home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / os2 / bltc127.zip / CZ.HLP (.txt) < prev    next >
CZ Help  |  1996-11-12  |  194KB  |  3,430 lines

  1. CZ_HELP!
  2. INDEX
  3. TUTORIAL_INDEX
  4. LICENSE_AGREEMENq
  5. LICENSE_A
  6. PRODUCT_SUPPORT
  7. STARTING_CZ
  8. USING_CZ
  9. USING_CZ_A
  10. USING_CZ_B
  11. ABOUT_CZ
  12. IS_BULLET
  13. IS_A_DATABASE
  14. IS_DBF
  15. IS_A_BTREE
  16. IS_A_NETWORK
  17. IS_FILE_LOCKING
  18. IS_NLS
  19. DESIGN_A_DB
  20. CREATE_A_DB
  21. ADD_TO_THE_DB
  22. QUERY_THE_DB
  23. UPDATE_THE_DB
  24. DELETE_A_RECORD
  25. COMPILE_WITH
  26. LIB_WITH
  27. CALL_BULLET
  28. SPECS_OVERALL
  29. SPECS_DBF
  30. SPECS_DBF_A
  31. SPECS_DBF_B
  32. SPECS_DBF_C
  33. SPECS_INDEX
  34. SPECS_INDEX_A
  35. SPECS_INDEX_B
  36. SPECS_INDEX_C
  37. SPECS_MEMORY
  38. SPECS_MEMORY_A
  39. SPECS_OS_CALLS
  40. SPECS_LANGUAGES
  41. SPECS_OSES
  42. SPECS_NETWORKS
  43. SPECS_PERFORMANC
  44. INITXB
  45. EXITXB
  46. ATEXITXB
  47. MEMORYXB
  48. BREAKXB
  49. BACKUPFILEXB
  50. STATHANDLEXB
  51. GETEXTERRORXB
  52. DVMONCXB
  53. CREATEDXB
  54. OPENDXB
  55. CLOSEDXB
  56. STATDXB
  57. READDHXB
  58. FLUSHDHXB
  59. COPYDHXB
  60. ZAPDHXB
  61. CREATEKXB
  62. CREATEKXB_A
  63. CREATEKXB_B
  64. CREATEKXB_C
  65. CREATEKXB_D
  66. CREATEKXB_E
  67. CREATEKXB_F
  68. OPENKXB
  69. CLOSEKXB
  70. STATKXB
  71. READKHXB
  72. FLUSHKHXB
  73. COPYKHXB
  74. ZAPKHXB
  75. GETDESCRIPTORXB
  76. GETRECORDXB
  77. ADDRECORDXB
  78. UPDATERECORDXB
  79. DELETERECORDXB
  80. UNDELETERECORDXB
  81. PACKRECORDSXB
  82. FIRSTKEYXB
  83. EQUALKEYXB
  84. NEXTKEYXB
  85. PREVKEYXB
  86. LASTKEYXB
  87. STOREKEYXB
  88. DELETEKEYXB
  89. BUILDKEYXB
  90. CURRENTKEYXB
  91. GETFIRSTXB
  92. GETEQUALXB
  93. GETNEXTXB
  94. GETPREVXB
  95. GETLASTXB
  96. INSERTXB
  97. UPDATEXB
  98. REINDEXXB
  99. LOCKXB
  100. UNLOCKXB
  101. LOCKKEYXB
  102. UNLOCKKEYXB
  103. LOCKDATAXB
  104. UNLOCKDATAXB
  105. DRIVEREMOTEXB
  106. FILEREMOTEXB
  107. SETRETRIESXB
  108. DELETEFILEDOS
  109. RENAMEFILEDOS
  110. CREATEFILEDOS
  111. ACCESSFILEDOS
  112. OPENFILEDOS
  113. SEEKFILEDOS
  114. READFILEDOS
  115. EXPANDFILEDOS
  116. WRITEFILEDOS
  117. CLOSEFILEDOS
  118. MAKEDIRDOS
  119. ACCESSPACK
  120. BREAKPACK
  121. COPYPACK
  122. CREATEDATAPACK
  123. CREATEKEYPACK
  124. DESCRIPTORPACK
  125. DOSFILEPACK
  126. DVMONPACK
  127. EXITPACK
  128. FIELDDESCTYPE
  129. HANDLEPACK
  130. INITPACK
  131. MEMORYPACK
  132. OPENPACK
  133. REMOTEPACK
  134. SETRETRIESPACK
  135. STATDATAPACK
  136. STATKEYPACK
  137. STATHANDLEPACK
  138. XERRORPACK
  139. ERRORS_BULLET
  140. ERRORS_BULLET_B
  141. ERRORS_BULLET_C
  142. ERRORS_BULLET_D
  143. ERRORS_DOS
  144. ERRORS_DOS_B
  145. ERRORS_DOS_C
  146. INITXBSRC
  147. EXITXBSRC
  148. ATEXITXBSRC
  149. MEMORYXBSRC
  150. BREAKXBSRC
  151. BACKUPFILEXBSRC
  152. STATHANDLEXBSRC
  153. GETEXTERRORXBSRC
  154. DVMONCXBSRC
  155. CREATEDXBSRC
  156. CREATEDXBSRC_A
  157. OPENDXBSRC
  158. CLOSEDXBSRC
  159. STATDXBSRC
  160. READDHXBSRC
  161. FLUSHDHXBSRC
  162. COPYDHXBSRC
  163. ZAPDHXBSRC
  164. CREATEKXBSRC
  165. OPENKXBSRC
  166. CLOSEKXBSRC
  167. STATKXBSRC
  168. READKHXBSRC
  169. FLUSHKHXBSRC
  170. COPYKHXBSRC
  171. ZAPKHXBSRC
  172. GETDESCRIPTORXBS
  173. GETRECORDXBSRC
  174. ADDRECORDXBSRC
  175. UPDATERECORDXBSR
  176. DELETERECORDXBSR4
  177. UNDELETERECORDSR
  178. PACKRECORDSXBSRC
  179. FIRSTKEYXBSRC
  180. EQUALKEYXBSRC
  181. NEXTKEYXBSRC
  182. PREVKEYXBSRC
  183. LASTKEYXBSRC
  184. STOREKEYXBSRC
  185. DELETEKEYXBSRC
  186. BUILDKEYXBSRC
  187. CURRENTKEYXBSRC
  188. GETFIRSTXBSRC
  189. GETEQUALXBSRC
  190. GETNEXTXBSRC
  191. GETPREVXBSRC
  192. GETLASTXBSRC
  193. INSERTXBSRC
  194. UPDATEXBSRC
  195. REINDEXXBSRC
  196. LOCKXBSRC
  197. UNLOCKXBSRC
  198. LOCKKEYXBSRC
  199. UNLOCKKEYXBSRC
  200. LOCKDATAXBSRC
  201. UNLOCKDATAXBSRC
  202. DRIVEREMOTEXBSRC!
  203. FILEREMOTEXBSRC
  204. SETRETRIESXBSRC
  205. DELETEFILEDOSSRCP
  206. RENAMEFILEDOSSRC
  207. CREATEFILEDOSSRC
  208. ACCESSFILEDOSSRCB
  209. OPENFILEDOSSRC
  210. SEEKFILEDOSSRC
  211. READFILEDOSSRC
  212. EXPANDFILEDOSSRC
  213. WRITEFILEDOSSRC
  214. CLOSEFILEDOSSRC
  215. MAKEDIRDOSSRC
  216. ~INDEX            CZ.HLP-BULLET for C
  217.  System 
  218.  Mid-level Record/Key Access 
  219. InitXB        
  220. CreateDXB    CreateKXB    GetDescriptorXB     FirstKeyXB     
  221. ExitXB        
  222. OpenDXB      OpenKXB      GetRecordXB         EqualKeyXB     
  223. AtExitXB      
  224. CloseDXB     CloseKXB     AddRecordXB         NextKeyXB      
  225. MemoryXB      
  226. StatDXB      StatKXB      UpdateRecordXB      PrevKeyXB      
  227. BreakXB       
  228. ReadDHXB     ReadKHXB     DeleteRecordXB      LastKeyXB      
  229. BackupFileXB  
  230. FlushDHXB    FlushKHXB    UndeleteRecordXB    StoreKeyXB     
  231. StatHandleXB  
  232. CopyDHXB     CopyKHXB     PackRecordsXB       DeleteKeyXB    
  233. GetExtErrorXB 
  234. ZapDHXB      ZapKHXB                          BuildKeyXB     
  235. DVmonCXB      
  236.                                               CurrentKeyXB   
  237.  High-level Access 
  238.  Network 
  239. GetFirstXB    InsertXB     
  240. LockXB           UnlockXB        LockKeyXB      
  241. GetEqualXB    UpdateXB     
  242. UnlockKeyXB      LockDataXB      UnlockDataXB   
  243. GetNextXB     ReindexXB    
  244. DriveRemoteXB    FileRemoteXB    SetRetriesXB   
  245. GetPrevXB                  
  246. GetLastXB                  
  247.  Low-level DOS Access 
  248.                            
  249. DeleteFileDOS    OpenFileDOS     WriteFileDOS   
  250.                            
  251. RenameFileDOS    SeekFileDOS     CloseFileDOS   
  252.  Move cursor to index item 
  253. CreateFileDOS    ReadFileDOS     MakeDirDOS     
  254.  and press <Enter>.        
  255. AccessFileDOS    ExpandFileDOS                  
  256. See: TUTORIAL_INDEX
  257. ~TUTORIAL_INDEX   CZ.HLP-BULLET for C
  258.  CZ.COM 
  259.  Using BULLET 
  260.  1.2 
  261. Starting_CZ   
  262. What:              How to:                                   
  263. Using_CZ      
  264.  is_BULLET          design_a_DB         compile_with         
  265. About_CZ      
  266.  is_a_database      create_a_DB         LINK_with            
  267.               
  268.  is_DBF             add_to_the_DB       LIB_with             
  269.  is_a_Btree         query_the_DB                             
  270.  Error Codes
  271.  is_a_network       update_the_DB      
  272.        
  273. Errors_BULLET 
  274.  is_file_locking    delete_a_record    
  275.  call_BULLET 
  276.        
  277. Errors_DOS    
  278.  is_NLS                                
  279.        
  280.               
  281.                     LICENSE_AGREEMENT   Product_Support      
  282.  Structure Pack Types 
  283.  Specifications 
  284. AccessPack       DVmonPack        RemotePack     
  285. Specs_Overall            
  286. BreakPack        ExitPack         SetRetriesPack 
  287. Specs_DBF                
  288. CopyPack         FieldDescType    StatDataPack   
  289. Specs_Index              
  290. CreateDataPack   HandlePack       StatKeyPack    
  291. Specs_Memory             
  292. CreateKeyPack    InitPack         StatHandlePack 
  293. Specs_OS_Calls           
  294. DescriptorPack   MemoryPack       XErrorPack     
  295. Specs_Languages          
  296. DOSFilePack      OpenPack                        
  297. Specs_OSes               
  298.                                                  
  299. Specs_Networks           
  300.                                                  
  301. Specs_Performance        
  302. See: License_Agreement
  303. ~License_Agreement
  304. Before using this software you must agree to the following:
  305.  1. You are not allowed to operate more than one (1) copy of this software
  306.     package at one time per license. This means that if you have 10 programmers
  307.     that COULD possibly use the BULLET library at the same time, you must also
  308.     have ten (10) BULLET licenses.
  309.  2. You are not allowed to distribute non-executable code containing BULLET
  310.     code. This means that you are not allowed to redistribute BULLET code as
  311.     another .LIB, for example. Also, if BULLET code is to be contained in a
  312.     Dynamic Link Library (DLL) then it must be part of a stand-alone product.
  313.     This means that you cannot provide a .DLL containing BULLET code if that
  314.     .DLL is to be used as a programming library for other programmers. If you
  315.     wish to distribute non-executable code containing BULLET code you must
  316.     obtain written permission from the author.
  317.  3. This license grants you the right to use the BULLET library code on a
  318.     royalty-free basis.
  319. See: License_a                                                          -MORE-
  320. ~License_a
  321.  4. BULLET is owned by the author, Cornel Huth, and is protected by United
  322.     States copyright laws and international treaty provisions. You are not
  323.     allowed to make copies of this software except for archival purposes.
  324.  5. You may not rent or lease BULLET. You may not transfer this license without
  325.     the written permission of the author. If this software is an update or
  326.     upgrade, you may not sell or give away previous versions.
  327.  6. You may not reverse engineer, decompile, or disassemble this software.
  328.  7. There are no expressed or implied warranties with this software.
  329.  8. All liabilities in the use of this software rest with the user.
  330.  9. U.S. Government Restricted Rights. This software is provided with
  331.     restricted rights. Use, duplication, or disclosure by the Government is
  332.     subject to restrictions as set forth in subparagraph (c)(1)(ii) of the
  333.     Rights in Technical Data and Computer Software clause at 52.227-7013.
  334.     Manufacturer is Cornel Huth/6402 Ingram Rd/San Antonio, TX 78238.
  335.     This agreement is governed by the laws of the state of Texas.
  336. See: Product_Support
  337. ~Product_Support
  338. Technical support in the use of Bullet is available for licensed
  339. users at the 40th Floor BBS or by way of the Internet.
  340. 40th Floor BBS: +1(210)684-8065  N-8-1
  341. Internet: support@40th.com
  342.           http://www.40th.com
  343. Response time is usually within 24 hours by internet e-mail or if
  344. you leave a message at the support BBS.  Alternatively, you may
  345. post a letter to
  346. Cornel Huth/6402 Ingram Rd/San Antonio TX 78238/USA.
  347. The latest 16-bit release of BULLET is available for download from
  348. the BBS by registered users, or $5 by postal mail, or from the web site (ask
  349. for instructions, if needed).  Re-createable bugs are fixed immediately.
  350. Report a new program bug and get the fix shipped free (include your mailing
  351. address with your report, even if it has not changed).  Past bugs are listed
  352. at the BBS and the web site.  Contact support if you have any questions or
  353. requests.
  354. See: Starting_CZ
  355. ~Starting_CZ
  356. At CZ's initial load it looks into the current directory for CZ.HLP, then in 
  357. the directory of CZ.COM, and last it looks for the pathname specified by the 
  358. DOS variable CZH (SET CZH=C:\DOC\CZ.HLP). Use /f: for alternate locations or 
  359. if CZ has any trouble locating its CZ.HLP file (C>cz /f:D:\BIN\CZ.HLP).      
  360. Load CZ.COM from the DOS command line. Options are:
  361.         /f:helpfile.ext       Use other than default CZ.HLP help file
  362.         /h# where n=1 to 4    Use alternate hot-key from default Alt-F1
  363.             #=1  Ctrl-h
  364.             #=2  F12
  365.             #=3  left+right Shift
  366.             #=4  Alt-left Shift
  367.         /u  uninstall CZ from memory (after initial load)
  368.         /s  temporarily put CZ to sleep by restoring all hooked vectors
  369.         /r  restore CZ from its sleep by rehooking vectors
  370.         /?  quick help
  371.  E.g., C>cz /f:D:\PRG_C\CBULLET.HLP   supply entire pathname when using /f:
  372.        C>cz /h1                       change hot key from Alt-F1 to Ctrl-H
  373. See: Using_CZ
  374. ~Using_CZ
  375. To activate CZ press the hot-key while the cursor is on the word you want to
  376. look up. Information on that word, if any, is displayed. If none is available,
  377. an index of help items in the dictionary is shown. Along the top-right of the
  378. index screens is the control bar. You can quickly move to the control bar by
  379. pressing <Home> or the See: line with <End>. Move the cursor to TUTORIAL_INDEX
  380. to select the second index screen or QUIT to return to whatever you were doing
  381. or over any index item. Then press <Enter> to move to that item's help entry.
  382. <F1> can be used as <Enter>. A mouse can also be used and is recommended.
  383. For example, to find out about CreateDXB, type it in your application and move
  384. the cursor on it. Press the hot-key. The CreateDXB screen is displayed. To see
  385. what pack type it uses, move to CreateDataPack (at Pack:) and press <Enter>.
  386. For a source example, move the cursor to Src: CreateDXBsrc. To go straight to
  387. the index from your application, press the hot-key with the cursor on a blank
  388. space. The <Esc> key returns you to your application.
  389. If there are more screens for the current topic the See: line has the same   
  390. topic name plus a letter, and -MORE- at the end. Move the cursor (or mouse)  
  391. to the topicname text (by using the <End> key) and press <Enter> (or click). 
  392. See: Using_CZ_a                                                         -MORE-
  393. ~Using_CZ_a
  394. CZ.COM can be loaded high but it is ESSENTIAL that you have at least 15K of  
  395. free UMB RAM available. It will load in as little as 4.5K but it will not    
  396. operate correctly. Use MEM/c to see how much Upper Memory RAM is available.  
  397. CZ opens the help file at installation. The help file is opened for Read-Only
  398. access with a Deny None sharing attribute. The file is closed when CZ is
  399. uninstalled (C>cz /u). CZ makes use of its own 256-byte stack.
  400. If you have several CZ help files, rename them to their particular application.
  401. For example:
  402. Rename the C BULLET CZ.HLP to CBULLET.HLP. Put CBULLET.HLP into your
  403. help files directory. Put SET CZH=C:\HELPFILES\CBULLET.HLP in your AUTOEXEC.BAT
  404. file. The next time CZ is installed it uses CBULLET.HLP from C:\HELPFILES.
  405. At anytime you can specify CZ.COM to use another help file. For example, if the
  406. current CZ help file is CBULLET.HLP but you want to use the QBULLET.HLP file,
  407. use C>cz /f:\helpfiles\qbullet.hlp. QBULLET.HLP then becomes the active file
  408. the next time you popup CZ.
  409. See: Using_CZ_b                                                         -MORE-
  410. ~Using_CZ_b
  411. Limitations:
  412. 1) CZ is a stable TSR but like all TSRs in a DOS system, unforseen events can
  413. take place that could conceivably cause the computer to crash. Therefore, it's
  414. recommended that you save your work often (you should do so whether a TSR is
  415. installed or not).
  416. See: About_CZ
  417. ~About_CZ
  418.               
  419.               
  420.                      CZ HELP                     
  421.               
  422.                                                  
  423.               
  424.       Context-sensitive Online Help Manager      
  425.               
  426.                                                  
  427.               
  428.                      for the                     
  429.               
  430.                                                  
  431.               
  432.                
  433.               
  434.               
  435.                
  436.                
  437.               
  438.                
  439.                
  440.               
  441.                
  442.                
  443.               
  444.                                                  
  445.               
  446.                 compiler libraries               
  447.               
  448.                                                  
  449.               
  450.               DOS C compiler version             
  451.               
  452.                                                  
  453.               
  454.                                                  
  455.               
  456.          Copyright 1992-1996  Cornel Huth        
  457.               
  458.                                                  
  459.               
  460. Ver 1.27         INT2F MuxID=C2         11-Nov-96
  461.               
  462. See: Specs_Overall
  463. ~is_BULLET - What?
  464. BULLET is a program module that handles the details of putting information to
  465. and getting information from your hard disk using a standard data file format
  466. called the Xbase DBF format with very fast and efficient index file routines.
  467. It can be used as-is by most DOS compilers.
  468. BULLET is written in 100% assembly language. Why? Two reasons. First, control.
  469. There's no compiler code or run-time library code in between BULLET and your
  470. data. Second, efficiency. BULLET knows exactly what it requires from the
  471. operating system and when. Result: fast, small, and robust applications.
  472. See: is_a_database
  473. ~is_a_database - What?
  474. A database is a collection of data arranged so that the it can be accessed as
  475. useful information. For example, let's say we have two files. Each consists of
  476. two fields. The first file has codenumber and score. The second file has a
  477. codenumber and name. Separately, the files are merely a collection of data.
  478. Together, however, they tie the name to the score:
  479.         score codenumber   codenumber name
  480.          99     100           100     John
  481.          87     155           105     Paul
  482.          66     125           110     George
  483.           :      :             :       :
  484. Codenumber 100 is John, who scored 99. The other members scores are not in the
  485. abbreviated data file listing.
  486. A database can be a single data file but more often it is a group of related
  487. data files and usually these data files are indexed by keys (in the index file,
  488. also called key file) so that very fast, direct access is possible.
  489. Ringo.
  490. See: is_DBF
  491. ~is_DBF - What?
  492. DBF is the file extension of dBASE III-compatible data files (filename.DBF).
  493. The file format is used by dBASE IV, FoxPro and many other database programs.
  494. Many programs can also use the file format to import/export data using it.
  495. The DBF format is the most common data file format used on PCs.
  496. A DBF-compatible data file consists 3 distinct areas. First is the data header.
  497. This contains information such as the number of records in the file. Second is
  498. the field descriptors. These descriptors define the makeup of each field in the
  499. record. The third is the record area. Each record is a logical unit of data.
  500. For example, a record, all of which are made up of the same fields but with
  501. different data, could (conceptually) look like this:
  502.                field 1         field 2         field 3       field n
  503.            
  504.   record 1 
  505. Johnson         
  506. Larry          
  507. 465310555     ...
  508.            
  509.   record 2 
  510. Aberdeen        
  511. Zara           
  512. 465230555     ...
  513.            
  514.   record n
  515. See: is_a_Btree  Specs_DBF
  516. ~is_a_Btree - What?
  517. A b-tree is a sorting method ideally suited to data structures maintained on a
  518. hard disk. It is very fast on retrieval and is inherently self-balancing during
  519. inserts and deletes. Self-balancing ensures performance remains consistent.
  520. The reason the b-tree is ideally suited to hard disks is that, when looking for
  521. a particular key, most of the time involved in accessing the key is spent by
  522. the hard drive moving to various locations on the disk. The task of a good
  523. access method is to reduce the number of seeks that the disk must perform. The
  524. b-tree accomplishes this by maintaining several keys (perhaps 50) on each node,
  525. with the necessary pointers to previous and following nodes. A b-tree of order
  526. 20 (19 keys per node) can find a key in a file of 1,000,000 keys in a MAXIMUM
  527. of 5 disk accesses, where each disk access visits a node.
  528. 'BASIC program to find *max* seeks needed/avg time
  529. Keys& = 1000000: KeysPerNode = 19: AvgSR = 25
  530. Order = KeysPerNode + 1
  531. max = (LOG((Keys& + 1) / 2) / LOG(Order / 2))
  532. PRINT "Max nodes accessed for"; Keys; "keys & b-tree of order"; Order;
  533. PRINT "is"; max; "nodes"
  534. PRINT "Max disk time based on avg seek+read of"; AvgSR;
  535. PRINT "ms is"; AvgSR / 1000 * max; "seconds"
  536. See: is_a_network  Specs_Index
  537. ~is_a_network - What?
  538. A network is a group of computers able to communicate with one another. Often
  539. called a LAN (local area network), a network allows resources to be shared.
  540. Sharing resources can lead to problems if steps are not taken to ensure that
  541. two computers don't try to share the same resource at the same time. For
  542. example, say two computers try to change the same record in a file on a network
  543. drive. Let's say both users are accessing the number of widgets in inventory.
  544. The first user gets there a micro-second before the second and allocates the
  545. last widget in stock. The second user comes in right after and, since the first
  546. user has not yet updated the inventory, allocates the very same widget. One
  547. widget, two users. When the first user updates the inventory, widgets in
  548. inventory is changed to 0 (previous - 1). The second updates the inventory in
  549. the same manner and sets widgets to 1 less what it was when it started, or 0
  550. also. You see the problem.
  551. In order to successfully share a file on a network, the file must first be
  552. locked to a single user. Once that user has locked the file, he has sole access
  553. to the data within it and he will not experience the scenario above. When the
  554. user has completed the changes, he unlocks the file so that others may use it.
  555. See: is_file_locking
  556. ~is_file_locking - What?
  557. File locking is a means to obtain exclusive access to a file. This is needed in
  558. cases of multiple programs or users accessing a shared file at the same time.
  559. There are several methods to ensure only one process or user has access to a
  560. file. The first method is to open the file so that while the file is open only
  561. your program can access any part of it. This is simple to implement and the
  562. operating system handles the details of this. However, it requires your program
  563. to open/close files all the time since no other process may access the file
  564. while it is open.
  565. Another method is to use byte-level locks. Also managed by the OS, this method
  566. allows for restricting access to any particular region within the file. Which
  567. regions are to be locked is to be determined by your program, however, and it
  568. can be complex to perform multiple locks at the byte, field, or record level.
  569. Another use of the byte-level lock is to specify that all bytes within the file
  570. are to be locked. This greatly simplifies the process of obtaining a lock and
  571. has the advantage over a file access lock of not needing to open/close the file
  572. for each lock. It is very fast and easy to implement. BULLET offers all three
  573. lock types.
  574. See: is_NLS
  575. ~is_NLS - What?
  576. NLS stands for National Language Support. This feature is available in DOS 3.3
  577. and later. BULLET makes use of NLS by getting from DOS the current DOS country
  578. collate-sequence table. The collate table is used to properly sort mixed-case
  579. character strings and also foreign (or non-USA) language character strings
  580. according to that country's alphabet. This is an option but is recommended.
  581. In addition, BULLET provides for a programmer-supplied collate-sequence table.
  582. See: design_a_DB
  583. ~design_a_DB - How to
  584. To design a database, above all else, know what information you require from
  585. it. Having established what you need to know, collect the data that lets you
  586. formulate this into useful information.
  587. For example, you want to track a class of students and determine how well they
  588. achieve on tests. The criterion you use is the test score. You determine that
  589. your data is 1) students, 2) tests, and 3) test scores. Too simplify, you use
  590. a single 20-character field for student, a numeric field for test number
  591. (1 to the n tests), and a numeric field for test scores (0 to 100).
  592. Since the objective is to track students' scores, arrange the data so that
  593. output consists of each student's score in test order. Do this by specifying an
  594. index file containing an index based on the student's name and test number:
  595.   char keyexpression[136];
  596.   strcpy (keyexpression,"STUDENT+TEST"); /* use two-field key */
  597. By using the routines of the database langauge, you can easily create the data
  598. and index files, add data, list student's scores, or make changes to the
  599. database. Note: these How_to examples are meant only to show the basis behind
  600. an operation.
  601. See: create_a_DB  CreateKXB
  602. ~create_a_DB - How to
  603. Having defined the database, create it. First, create the datafile based on the
  604. 3 fields you defined in your design. To do this, allocate an array for the
  605. field descriptors for the number of fields (see also CreateDataPack):
  606. struct fielddesctype fieldlist[3];
  607. strcpy(fieldlist[0].fieldname,"STUDENT\0\0\0");  /* 0-fill all fieldnames */
  608. fieldlist[0].fieldtype, 'C';                  
  609. fieldlist[0].fieldlen = 20;                   
  610. The fieldlist is a         
  611. fieldlist[0].fielddc = 0;                     
  612. in CDP (CreateDataPack):   
  613. strcpy(fieldlist[1].fieldname,"TEST_TAKEN");  
  614. CDP.func=CREATEDXB;        
  615. fieldlist[1].fieldtype, 'N';                  
  616.   :        :               
  617. fieldlist[1].fieldlen = 1;                    
  618. CDP.fieldlistptr=fieldlist;
  619. fieldlist[1].fielddc = 0;                     
  620.   :        :               
  621. strcpy(fieldlist[2].fieldname,"SCORE_WAS\0"); 
  622. fieldlist[2].fieldtype, 'N';
  623. fieldlist[2].fieldlen = 3;
  624. fieldlist[2].fielddc = 0;
  625. Call CreateDXB to create the data file. To create the index file, first open
  626. the data file just created, then call CreateKXB to create the index file. Open
  627. the index file so we can use it (data file is already open).
  628. See: add_to_the_DB  CreateDXB
  629. ~add_to_the_DB - How to
  630. Once you have the database designed and the data and key files created and open
  631. you can start putting the student's test data into it. Note that the DBF-format
  632. requires that all data in a data file be in ASCII format. This means that we
  633. must convert the numeric test score into its ASCII form. C has the ITOA()
  634. function to do this. In addition, numbers generally should be right-justified
  635. in their field.
  636. Note that BULLET does not require that you use only ASCII field data. If you
  637. want to forgo dBASE compatibility, binary data can be used directly in the
  638. fields.
  639. See: query_the_DB  InsertXB
  640. ~query_the_DB - How to
  641. Now that you have data in the database you want to see what's in there. Since
  642. the index file is in "STUDENT+TEST" order, the information we'll be getting
  643. out of the database is in Student name order, with each student's scores in
  644. test number order.
  645. If we want to look at all the students, we can use GetFirstXB to retrieve the
  646. first student's score for the first test. GetNextXB retrieves the next record
  647. (the first student's score for the second test), and so on. When all records
  648. have been retrieve GetNextXB returns an End Of File error code.
  649. If we want to look at a particular student's score only, we can use GetEqualXB
  650. to go directly to a student's first test score. GetNextXB get his next and so
  651. on until GetNextXB retrieves the next student's first test score. You can stop
  652. at this point (student names no longer match).
  653. We might also want to find all students who scored less than 65 on any test. To
  654. do this we can GetFirstXB, check SR.score for < 65 and if so print that record.
  655. Continue by using GetNextXB, printing each record that has a score < 65.
  656. See: update_the_DB  GetFirstXB
  657. ~update_the_DB - How to
  658. To update a particular record in the database we must first locate and identify
  659. it using one of the get routines such as GetEqualXB. The Get() routine return
  660. the record data, and also the physical record number of the record accessed,
  661. into the AccessPack RecNo. Having used one of the Get() routines to read the
  662. data record from disk to memory, you can make any changes to the data record in
  663. memory. E.g., if a student's score needs to be changed from a 69 to a 96, first
  664. find the record (and its RecNo), then update the score field.
  665. Note that any change to a key field will initiate a key file update
  666. automatically.
  667. See: delete_a_record  UpdateXB
  668. ~delete_a_record - How to
  669. To delete a particular record in the database we must first locate it using
  670. one of the get routines such as GetEqualXB. These Get() routines return the
  671. actual record number of the data record accessed by Get() into the AccessPack
  672. RecNo. Having used one of the Get() routines to find the data record, make a
  673. call to the delete function.
  674. The DeleteRecordXB routine does not physically remove the record from the data
  675. file but instead tags it as being "deleted".
  676. See: Compile_with  DeleteRecordXB
  677. ~Compile_with - How to
  678. To create an EXE file using Turbo C, comile you source using the medium,
  679. large, or huge memory models. No special compiler switches are required other
  680. than choosing the correct model.
  681. For example, if you have a single-module C source file called STUGRADE.C,
  682. compile it:
  683.  C>tcc -ml studgrade BULLET.lib
  684. If successful, the LINK program will automatically be called and the EXE
  685. program will be ready to run.
  686. It couldn't be simpler. One .LIB.  One .H.
  687. See: LIB_with
  688. ~LIB_with - How to
  689. BULLET.LIB is composed of many separate assembly language modules. All these
  690. modules have been combined into a single, easy-to-use .LIB library. While it
  691. is possible to combine, or add, other .OBJ files or even other .LIB files to
  692. BULLET.LIB, I do NOT, -NOT-, recommend that you do so.
  693. If you need to use two or more libraries with your programs, no problem, LINK
  694. can handle as many as you have. When LINK prompts you for a library file, just
  695. enter BULLET.LIB followed by any other library you need. For example:
  696.  C>LINK
  697.  Microsoft (R) Segmented-Executable Linker  Version 5.50
  698.  Copyright (C) Microsoft Corp 1984-1990.  All rights reserved.
  699.  Object Modules [.OBJ]: STUGRAD1+STUGRAD2+STUB
  700.  Run File [STUGRAD1.EXE]: STUGRADE.EXE
  701.  List File [NUL.MAP]: nul
  702.  Libraries [.LIB]: BULLET;
  703. Consult your linker programs documentation for specifics.
  704. See: call_BULLET
  705. ~call_BULLET - How to?
  706. BULLET is called through a single entry point. The only argument passed to it
  707. is a far pointer to the control pack using the Pascal calling convention. The
  708. first two entries in this pack are the function to be performed and the
  709. function return status. BULLET is a function call returning an integer status
  710. value. See BULLET.H for more.
  711. Each function (or routine) uses a prescribed pack format. For example, some
  712. routines need only know the handle of the file, along with the function number
  713. itself. So, to flush a data file, for example, you would do the following:
  714.  struct handlepack HP;
  715.  HP.func = FLUSHDHXB;         /* FLUSHDHXB is defined as a CONST in BULLET.H */
  716.  HP.handle = file2flushhandle;/* handle as returned from the Open() routine  */
  717.  rstat = BULLET(&HP);         /* do the actual call to BULLET                */
  718. The value of rstat is set to the completion code as returned by the FlushDHXB
  719. routine. It is the same as the value returned in HP.stat *IN ALL BUT A FEW*  
  720. cases: InsertXB, UpdateXB, ReindexXB, and LockXB. These routines return not  
  721. the actual error code, but rather a transaction index number of the access   
  722. that failed. See those routines for more information.                        
  723. See: is_BULLET  FlushDHXB
  724. ~Specs_Overall
  725. BULLET is dBASE III/III+/IV .DBF-compatible. This format is compatible with a
  726. large base of software programs including the latest database packages such as
  727. dBASE IV and FoxPro. Spreadsheet packages such as Excel and 1-2-3 can directly
  728. import BULLET DBF data files, too. And because of BULLET's versatility, it can
  729. also create very non-standard data files. This may be a useful feature if data
  730. secrecy is of concern.
  731. BULLET requires MS-DOS 3.30 or above. It uses 19K of code/static data space and
  732. requires at least 40K of workspace. 140K of workspace is ideal.
  733. Overall Specifications:
  734.               DBF           (per file)          INDEX
  735.       
  736.     Max records: 16,777,215                Max nodes: 65,535
  737.   Record length: 2-4000 (8192)              Max keys: 4,063,170
  738.      Max fields: 128 (255)                Key length: 1-64
  739.    Field length: 1-254 (255)          Max key fields: 16
  740. Total open index plus data files can be up to 255. Numbers in () indicate
  741. extended specifications.  Maximum index file size is 32MB.
  742. See: Specs_DBF
  743. ~Specs_DBF
  744. To remain compatible with other dBASE III .DBF platforms you should restrict
  745. your data files to the following specifications:
  746.  File ID byte: 3  (83hex if .DBF has memo field, not currently supported)
  747.  Max record size: 4000 bytes  Max fields/rec: 128   Max field size: 254 bytes
  748.  Allowable field name characters: A-Z and the _ (upper-case)
  749.  Allowable field types:
  750.   C-character, 1-254 bytes
  751.   D-date, 8 bytes, in the format YYYYMMDD (19920531)
  752.   L-logical, 1 byte, either space, "T" or "Y", "F" or "N"
  753.   M-memo, 10 bytes, used as pointer into .DBT file (currently not supported)
  754.   N-numeric, 1-19 bytes, ASCII format, uses explicit decimal if needed...
  755.     ...decimal places may be 0, or 2 to (field size - 3) but no more than 15
  756. Restrict all data in .DBF fields to ASCII. This means you should convert binary
  757. data to the equivalent ASCII representation, e.g., if you have the binary value
  758. 22154, it must first be converted to the string "22154" before you can store it
  759. to the .DBF data file. So, while your in-program code deals with binary data,
  760. your I/O code must convert it to/from ASCII. This is a dBASE-compatibility
  761. issue only. If you can forgo these requirements you can use binary fields, any-
  762. character field names, record sizes to 8192 bytes, and up to 255 fields.
  763. See: Specs_DBF_a                                                        -MORE-
  764. ~Specs_DBF_a
  765. A dBASE III .DBF is composed of 3 sections: the header, the field descriptors,
  766. and the data area.
  767. The header structure (first 32 bytes of file):
  768.     Name     Type   Offset  Meaning
  769.  FileID      byte        0  data file type id, 03 standard (43,63,83,88h)
  770.  LastYR      byte        1  last update year, binary
  771.  LastMo      byte        2  last update month, binary
  772.  LastDA      byte        3  last update day, binary
  773.  NoRecs      long        4  number of records in file
  774.  HdrLen      word        8  length of header, including field descriptors, +1
  775.  RecLen      word       10  length of data record including delete tag
  776.  internal    byte    12-31  reserved
  777. The last update values are updated to the current date whenever the .DBF file
  778. is flushed or closed. Likewise, the NoRecs value is updated whenever a record
  779. is added to the .DBF. The FileID is specified when you create the file, HdrLen
  780. and RecLen are computed and stored when the file is created, too.
  781. See: Specs_DBF_b                                                        -MORE-
  782. ~Specs_DBF_b
  783. The field descriptor format (follows header, one per field):
  784.     Name     Type   Offset  Meaning
  785.  FieldName   char        0  field name 10 ASCII characters, A-Z or _ (0-filled)
  786.         0T   byte       10  field name zero-termintor (must be 0)
  787.  FieldType   char       11  field type (C D L M N)
  788.  internal    long       12  reserved
  789.  FieldLen    byte       16  length of this field
  790.  FieldDC     byte       17  decimal count
  791.  internal    byte    18-31  reserved
  792.       
  793. The unused bytes in the FieldName must be set to zeroes (CHR$(0)).
  794. Each field is described by a 32-byte descriptor. The first field's descriptor
  795. starts right after the header proper, at offset +32. After the last field
  796. descriptor is data byte ASCII 13. (Note: the orginal dBASE III has a 0 byte
  797. following this ASCII 13.) Immediately following this is the actual record data.
  798. See: Specs_DBF_c                                                        -MORE-
  799. ~Specs_DBF_c
  800. The data record format:
  801. The first record is located at offset HdrLen (from the header). The first byte
  802. of each record is a delete tag. This tag is maintained by the BULLET routines.
  803. A space, ASCII 32, means the record is not deleted; an asterisk, ASCII 42,
  804. means the record has been deleted (marked as deleted, often this is used as a
  805. method to temporarily tag records, for whatever purpose).
  806. Following the tag is the data for each field, not delimited (i.e., the fields
  807. run together without anything separating them). The second record is at offset
  808. HdrLen+reclen. The start offset of any record in the file can be computed as
  809. (recordnumber - 1) * reclen + HdrLen. All data is in ASCII form.
  810. An EOF marker (ASCII 26) is placed at the end of the last record.
  811. See: Specs_Index
  812. ~Specs_Index
  813. BULLET uses a proprietary, modified b-tree index method to manage the index
  814. files. The supported key types are:
  815.     Type     Length  Meaning
  816.  Character     1-64  ASCII, NLS, or user-supplied sort table
  817.  Integer          2  signed or unsigned 16-bit value
  818.  Long Int         4  signed or unsigned 32-bit value
  819. In addition to the above types, BULLET allows for unique or duplicate keys in
  820. the index file. If duplicates are allowed, BULLET enumerates each key with an
  821. enumerator word (see FirstKeyXB).
  822. The key may be composed of up to 16 character fields or substrings within those
  823. fields. Numeric fields are considered character fields by BULLET unless the key
  824. is set to binary (see KeyFlags). Integer or LongInt binary keys can be composed
  825. of a single field only. The key expression is specified in text (e.g., "LNAME+
  826. SUBSTR(FNAME,1,1)+MI") and is fully evaluated when the index file is created.
  827. A BULLET index file is composed of 3 sections: the header, the collate-sequence
  828. table, and the node/key entry area.
  829. See: Specs_Index_a                                                      -MORE-
  830. ~Specs_Index_a
  831. The header structure:
  832.     Name     Type   Offset  Meaning
  833.  FileID      byte        0  index file type id, 20
  834.  RootNode    word        1  root node number
  835.  Keys        24bit       3  number of keys in index file
  836.  AvalNode    word        6  node number available for reuse
  837.  FreeNode    word        8  next free node number
  838.  KeyLen      byte       10  key length
  839.  NodeKeys    byte       11  number of keys that fit on a node
  840.  CodePage    word       12  code page ID
  841.  CtryCode    word       14  country code
  842.  internal    byte    16-21  reserved
  843.  KeyFlags    word       22  key flags
  844.  KeyExprn    byte   24-159  key expression
  845.  internal    byte      160  reserved
  846.  KeyXFlds    byte      161  number of fields used by key (1-16)
  847.  KeyXlate    byte  162-225  translated key expression
  848.  internal    byte  226-253  reserved
  849.  CTsize      word      254  collate-sequence table size
  850. See: Specs_Index_b                                                      -MORE-
  851. ~Specs_Index_b
  852. The collate-sequence table structure:
  853.  table      byte   256-511  sort weight table of ASCII character 0-255
  854. Node/key entry structure (first entry is in node #1, file offset 512):
  855.   2A  0A 00  KEY123  7B 00 00  12 00  KEY178  B2 00 00  0C 00 ...
  856.    1.   2.     3.       4.       5.     6.       7.       8.   9.
  857.       
  858.  1. Key count for that node (first byte of each node)
  859.  2. 16-bit node back pointer (for non-leaf nodes, 0 if leaf node)
  860.  3. First key value, "KEY123" in this case
  861.  4. 24-bit data record pointer (low word/hi byte) 7Bh = DBF record number 123
  862.  5. 16-bit node forward ptr/back ptr (for non-leaf nodes, 0 if leaf node)
  863.     --in this case, it indicates that the key following KEY123 is in node# 12h
  864.     --and also that the key before KEY178 is in that node as well
  865.  6. Second key (here "KEY178")
  866.  7. 24-bit data pointer (record number in DBF)
  867.  8. 16-bit forward node pointer (for non-leaf nodes, 0 if leaf node)
  868.  9. Repeat 6 to 8 for each key on node. (node size is 512 bytes)
  869. See: Specs_Index_c                                                      -MORE-
  870. ~Specs_Index_c
  871. As in many b-tree implementations, BULLET's index files maintain an average
  872. load percentage of approximately 66%. This means that in any given node, 66% of
  873. the available space is in use. The free space in the node is attributable to
  874. the constant reshaping of the file as keys are inserted or deleted, causing the
  875. nodes to be split and merged. A split will occur when an insert needs to add a
  876. key to an already full node; a merge will occur when a neighboring node is
  877. small enough to be merged into a just split node. This constant prune-and-graft
  878. of the b-tree results in a node load of about 66% (50% in degenerate cases such
  879. as with already sorted data). It's this aspect of the b-tree that makes it a
  880. consistent performer and a widely-used method of managing index files.
  881. The following formula can be used to determine the number of keys that an index
  882. file can hold:
  883.   MaxKeys = MaxNodes * MaxKeysPerNode * LoadFactor
  884.   MaxKeys = 65535 * 509/(keylen+5) * .66
  885. The load factor can be increased to ~95% by using the ReindexXB routine. This
  886. load factor results in superior retrieval speeds since there are more keys on
  887. each node. Insertion speed will be decreased, however, since splitting will
  888. occur more frequently, though perhaps not noticeably.
  889. See: Specs_Memory
  890. ~Specs_Memory
  891. BULLET allocates memory on an as-needed basis. When linked to an executable
  892. program, BULLET makes use of 17.5K of code space and about 1.5K of static
  893. DGROUP data space. To accomodate the wide variety of compilers, BULLET's API
  894. structure will have the linker included all of the library into your final EXE
  895. program.
  896. All runtime memory allocations are obtained from the operating system (the
  897. far heap).
  898. The amount of memory that BULLET requires is based on which routines are used.
  899. See the next screen for a list of the routines that make malloc calls to the
  900. operating system and how much memory they require.
  901. Note that the malloc calls are made with DOS INT21/48.
  902. See: Specs_Memory_a  MemoryXB                                           -MORE-
  903. ~Specs_Memory_a
  904. Routines making dynamic memory allocations and amount (within 
  905.  16 bytes):
  906.   Routine           Bytes        Basis
  907. InitXB                  272   permanent, released when program ends (JFTmode=1)
  908. BackupFileXB             32K  temp, released when routine exits
  909. CreateDXB        48+(NF*32)   temp, released when routine exits (NF=NoFields)
  910. CreateKXB               544   temp, released when routine exits
  911. OpenDXB     144+((1+NF)*32)   semi-permanent, released when file closed
  912. OpenKXB                1264   semi-permanent, released when file closed
  913. PackRecordsXB      RL to 64K  temp, released when routine exits (RL=RecLength)
  914. ReindexXB        32K to 128K  temp, released when routine exits
  915. UpdateXB              2K+RL   temp, released when routine exits (RL=RecLength)
  916. For example, when BackupFileXB is called it attempts to allocate 32K from the
  917. OS. If 32K is not available, BackupFileXB returns with an error code of 8 (DOS
  918. error #8, not enough memory). If you won't be using Backup or Reindex, BULLET
  919. can make do with much less memory (use table above).
  920. Needed stack space is 4K (max) for ReindexXB. Other routines can operate with
  921. less than 1K of stack space. In other words, stack use is minimal.
  922. See: Specs_OS_calls
  923. ~Specs_OS_calls
  924. BULLET makes use of the following operating system calls:
  925. INT21/25 DOS_setvector                  INT21/44/0B DOS_setsharingretrycount
  926. INT21/2A DOS_getdate                    INT21/48 DOS_malloc
  927. INT21/30 DOS_version                    INT21/49 DOS_free
  928. INT21/35 DOS_getvector                  INT21/51 DOS_getpsp
  929. INT21/39 DOS_makedir                    INT21/56 DOS_renamefile
  930. INT21/3D DOS_openfile                   INT21/59 DOS_getextendederror
  931. INT21/3E DOS_closefile                  INT21/5A DOS_createtempfile
  932. INT21/3F DOS_readfile                   INT21/5B DOS_createnewfile
  933. INT21/40 DOS_writefile                  INT21/5C DOS_lockunlockfile
  934. INT21/41 DOS_deletefile                 INT21/65/01 DOS_getextendedcountryinfo
  935. INT21/42 DOS_movefileptr                INT21/65/06 DOS_getcollatesequencetable
  936. INT21/44/09 DOS_isdriveremote           INT21/67 DOS_sethandlecount
  937. INT21/44/0A DOS_isfileremote            INT2F/10/00 DOS_isshareinstalled
  938. No other operating system calls are made. No BIOS calls are made.
  939. See: Specs_Languages
  940. ~Specs_Languages
  941. BULLET is compatible with most DOS compilers. The only requirements are that
  942. your compiler allow you to:
  943.  1. Call a library routine via a FAR call using PASCAL calling convention
  944.  2. Pass a far pointer (of the parameter pack) on the stack, by value
  945.  3. Supply far pointers to the various pack parameters
  946.  4. Be able to return an integer value from the FAR call
  947.     (this is optional but recommended for the transaction-based routines)
  948. These requirements can be met with most BASIC, C, and other-language DOS
  949. compilers.
  950. CZ online help is currently available in BASIC and C versions. Others are
  951. pending. You should be able to do well with either of these versions using
  952. other-language compilers since the only difference is the source code examples.
  953. See: Specs_OSes
  954. ~Specs_OSes
  955. BULLET is currently available only for MS-DOS and compatible operating systems.
  956. It requires DOS 3.3 or higher.
  957. To provide efficient memory use, BULLET uses a single-buffer cache per index
  958. file. The single-buffer cache also provides for very quick network access since
  959. a minimum amount of memory needs to be flushed when releasing control of BULLET
  960. files. For maximum speed, however, an external high-performance disk cache can
  961. be used. Hyperdisk is a good choice (shareware, $50+). A properly configured
  962. cache can increase BULLET's performance from 10 to 300%. The most improvement
  963. is with the InsertXB routine. The least is with ReindexXB and PackRecordsXB,
  964. which do most of their work in temporarily allocated memory. Hyperdisk is about
  965. the best designed disk cache available for PCs. SmartDRV 4.x is also good.
  966. If you do not use a disk cache then it's recommended that you set your BUFFERS=
  967. statement in CONFIG.SYS to at least 20 or 30. Even without a disk cache, BULLET
  968. is still very fast. Also, be sure to set your FILES= to the number of files
  969. that you'll be opening at any one time. If you set FILES=20 you can have BULLET
  970. open 14 files (CZ.COM uses 1 and DOS reserves 5 more). You can set FILES=255
  971. allowing BULLET to open up to 249 files at one time.
  972.                  DO NOT set FILES= to a value greater than 255.
  973. See: Specs_Networks
  974. ~Specs_Networks
  975. BULLET currently operates on all DOS-compatible network platforms.
  976. Be sure to install SHARE.EXE (or compatible) on the server and, if you are
  977. mutlitasking, on your local machine. If you'll be opening many files you
  978. should extended the default SHARE file-sharing information space and the number
  979. of locks that can performed at one time. The DOS 5.0 default is /F:2048 and
  980. /L:20. This allocates 2K for file-sharing info space and allows 20 consecutive
  981. locks to be active. If the F: value is too low, error 5 (extended error 32) is
  982. returned on an open attempt. If you extend the JFT in InitXB and plan to use
  983. many files, say more than 50, be sure to extend /F: by 2K for every 50
  984. additional files and set the /L: to the number of files you plan on having
  985. open. If L: is too low, error 1 (ext err 36) is returned on a lock attempt.
  986. As an example, if you'll be using 100 files, set FILES=106 in CONFIG.SYS, set
  987. SHARE /F:4096 /L:106, and IP.JFTmode=1 for InitXB. These values are a minimum.
  988. If you have more than one process active, you need to account for other apps.
  989. Note that Windows always returns a "SHARE is installed" using the DOS detection
  990. routines used by BULLET. To determine if SHARE is actually installed, attempt
  991. to perform a lock using one of the LockXB routines. An error code indicates
  992. that SHARE (or compatible) is not installed.
  993. See: Specs_Performance
  994. ~Specs_Performance
  995.  Test: Reindex 1,000 to 1,000,000 records (BC_LAI10.C)
  996.        DBF: extended DBF using binary sort field
  997.        key: LONG+SIGNED+UNIQUE                        Machine: 486/33 SHO
  998.  1Meg
  999.                                                      *
  1000.      
  1001.      
  1002.                                     *
  1003.      
  1004.                    Records  Time  Reindex Rate
  1005.      
  1006.        *           -------  ----  ------------
  1007.  100k
  1008.   *                   1000   < 1  1000+/sec
  1009.      
  1010.                       5000     2    2500
  1011.      
  1012.  *                   10000     4    2500
  1013.      
  1014. *                    25000     7    3571   3500+ records indexed/second!
  1015.      
  1016.                      50000    14    3571   Times in table are in seconds
  1017.   10k
  1018. *                   100000    28    3571
  1019.      
  1020.                     200000    81    2469
  1021.      
  1022. *                   500000   355    1408
  1023.      
  1024.                    1000000  1124     890
  1025.    1k
  1026.      
  1027.  time (secs)  100       200       300       400       18:00     20:00 (min)
  1028. See: Specs_Overall
  1029. ~InitXB
  1030. Pack: InitPack          Src: InitXBsrc          Func:   0/System
  1031. Before using any routine you must initialize the BULLET file system.
  1032. If you want more than the standard number of file handles, set InitPack.JFTmode
  1033. to 1. This expands the current process's Job File Table to allow 255 open files
  1034. maximum.
  1035. On return the DOS version (INT21/30h) is in InitPack.DOSver. Major version in
  1036. the high byte. Minor in the low. The BULLET version (*100) is returned as is
  1037. the address of the ExitXB routine. You can use this address to register ExitXB
  1038. with your own _atexit function if your runtime library does not provide _atexit
  1039. already.
  1040. Note: _atexit is a routine available in most DOS, OS/2, and ANSI runtime
  1041. library code and is called just prior to the program ending. See AtExitXB for
  1042. information on what to do if your library does not have _atexit.
  1043. See: ExitXB
  1044. ~ExitXB
  1045. Pack: ExitPack          Src: ExitXBsrc          Func:   1/System
  1046. Before ending your program you should call ExitXB to close any open BULLET
  1047. files. This also will release any memory still allocated to those files.
  1048. This restores the default keyboard break handlers if they were changed.
  1049. In normal operation you would see to closing all files yourself. However, if
  1050. your program fails to reach the programmed end, it's very possible that files
  1051. may still be left open. It is essential that you properly close all BULLET
  1052. files before ending. There are two methods to achieve this:
  1053. 1. Direct you startup code so that on fatal errors, your program executes
  1054. ExitXB before returning to DOS.
  1055. 2. Use AtExitXB to automatically register ExitXB to be executed in the normal
  1056. shut-down code of the compiler. This method is preferred.
  1057. See: AtExitXB
  1058. ~AtExitXB
  1059. Pack: ExitPack          Src: AtExitXBsrc        Func:   2/System
  1060. Used to automatically close all BULLET files, release allocated memory, and
  1061. restore the default Break handlers when your program ends. Your compiler
  1062. generates specific code to be executed in the course of ending your program.
  1063. AtExitXB registers the ExitXB routine to be performed in this compiler-
  1064. generated code.
  1065. This routine is standard in most DOS, OS/2, and ANSI runtime libraries. If   
  1066. yours does not have _atexit, then you must link with the supplied            
  1067. NOATEXIT.OBJ file:                                                           
  1068.                                                                              
  1069. C>link YOURPRG + NOATEXIT, ...                                               
  1070. You can tell if your compiler doesn't supply _atexit at link time. LINK reports
  1071. '_atexit' : unresolved external. Add NOATEXIT.OBJ as described above.
  1072. Be sure that your _atexit routine is for the medium, large, or huge memory
  1073. models since BULLET uses multiple code segments and far calls.
  1074. See: MemoryXB  ExitXB  BreakXB
  1075. ~MemoryXB
  1076. Pack: MemoryPack        Src: MemoryXBsrc        Func:   3/System
  1077. This is the only BULLET routine that can be used before InitXB. It reports the
  1078. largest free block of memory available from the OS. This memory does not
  1079. include fragmented memory or UMB memory that BULLET can and will use.
  1080. With DOS able to use UMB memory, memory for BULLET requests may be provided
  1081. from this region. You can use StatPack.HereSeg from StatXB to locate from which
  1082. segment address the allocations are being made. Anything above C800h is UMB.
  1083. See: BreakXB  StatXB  OpenDXB  OpenKXB
  1084. ~BreakXB
  1085. Pack: BreakPack         Src: BreakXBsrc         Func:   4/System
  1086. Disables system response to Control-C and Control-Break keys preventing users
  1087. from inadvertently exiting the program without first doing a BULLET shutdown.
  1088. It's REQUIRED that you reinstate the default break handlers with this routine
  1089. before ending your program. ExitXB automatically reinstates the default break
  1090. handlers.                                                                    
  1091. This routine will not disable Control-Alt-Delete (a warm-boot). If the user is
  1092. at this point, he may prefer to exit via a warm-boot rather than reset the
  1093. machine.
  1094. This routine will not surpress the ^C displayed by DOS. If you don't want the
  1095. ^C to be displayed move the cursor to a location off-screen, say, row 26.
  1096. See: BackupFileXB  ExitXB
  1097. ~BackupFileXB
  1098. Pack: CopyPack          Src: BackupFileXBsrc    Func:   5/System
  1099. Copy an open BULLET key or data file. BULLET repacks and reindexes files in-
  1100. place, requiring less disk space to perform the function. BackupFileXB allows
  1101. you to safely copy a file before doing this.
  1102. This function is recommended prior to packing a data file with PackRecordsXB 
  1103. since the data is very valuable. There is probably little need to do so when 
  1104. reindexing an index file since index files can be constructed very easily    
  1105. from the data file but a CopyKHXB to preserve the key expression is quick    
  1106. and recommended.                                                             
  1107. See: StatHandleXB  PackRecordsXB  ReindexXB
  1108. ~StatHandleXB
  1109. Pack: StatHandlePack    Src: StatHandleXBsrc    Func:   6/System
  1110. Get information on a DOS file handle number to determine if it is a BULLET file
  1111. and if so, if that file is a BULLET key or data file.
  1112. If the returned ID value is 0, the handle is to a BULLET index file. ID=1 then
  1113. the handle is a BULLET .DBF file. ID= -1 then the handle is not a BULLET file.
  1114. See: CreateDXB  StatDXB  StatKXB
  1115. ~GetExtErrorXB
  1116. Pack: XErrorPack        Src: GetExtErrorXBsrc   Func:   7/System
  1117. Get the extended error information for the last operation. This information
  1118. includes the extended error code, the error class, the recommended action, and
  1119. the location of the error. See Errors_DOS for the extended error meaning an
  1120. Errors_DOS_c for the class, action, and locus code meanings.
  1121. Note that on fatal DOS errors, such as an open floppy drive door, the extended
  1122. error code returned is 83 - fail on INT24. This indicates that the INT24
  1123. handler was invoked by DOS and that the INT24 handler told DOS to ignore the
  1124. error. (BULLET invokes its own INT24 handler each time it accesses the DOS file
  1125. system and restores it promptly after the access.) In such cases, this extended
  1126. error code is less informative than the standard return code and, the other
  1127. 'extended' information should be disregarded. (In fatal DOS errors the standard
  1128. return code IS the extended error code.)
  1129. This routine returns the extended error information for the LAST DOS system  
  1130. error. This information remains the same until the next DOS system error.    
  1131. See: CreateDXB  Errors_DOS
  1132. ~DVmonCXB
  1133. Pack: DVmonPack         Src: DVmonCXBsrc        Func:   9/DEBUG
  1134. Control BULLET debug monitor.
  1135. This routine is available only in the debug engine.                          
  1136. The monitor displays in realtime the state of a data file handle, or an index
  1137. and data file handle pair if an index handle is specified. DVmonCXB is best
  1138. used on dual-display systems in which the video output is sent to the secondary
  1139. video monitor. In any case, a 4000-byte screen image is updated in real-time.
  1140. To use the monitor, set mode=1, handle=file to monitor, and VideoSeg=segment
  1141. address of 4000-byte area. The typical VideoSeg would be to video memory. If
  1142. you have a color system as the main monitor and a mono as the secondary, set
  1143. VideoSeg=0xB000. Detail system stats are continually updated to the secondary
  1144. monitor. If you have a single monitor with at least 2 video pages, set VideoSeg
  1145. to your base address plus the page size\16, typically 0xB800+(4096/16). If you
  1146. have only a single-page video system, you can allocate a 4000-byte memory area
  1147. and update the video manually by moving it to your video display (80x25).
  1148. See: CreateDXB  StatDXB  StatKXB
  1149. ~CreateDXB
  1150. Pack: CreateDataPack    Src: CreateDXBsrc       Func:  10/Mid-level
  1151. Create a new BULLET .DBF data file. Before using this routine allocate a field
  1152. description array of TYPE FieldDescType for at least as many fields as are in
  1153. the record.
  1154. Conventional dBASE .DBF files have a FileID=3. Other possible FileIDs that you
  1155. may come across are (in hex):
  1156.  43h \__ are special-use Xbase IV DBF files, BULLET can process these file IDs
  1157.  63h /                                    since they are similar to ID type 3
  1158.  83h --- this DBF file has an Xbase III/III+ memo field/file
  1159.  88h --- this DBF file has an Xbase IV memo field/file
  1160. In creating your .DBF files, specify FileID=3 to ensure compatibility across 
  1161. Xbase versions.                                                              
  1162. BULLET makes no special use of the FileID byte.
  1163. See: OpenDXB  FieldDescType  CreateKXB
  1164. ~OpenDXB
  1165. Pack: OpenPack          Src: OpenDXBsrc         Func:  11/Mid-level
  1166. Open an existing .DBF data file for use. You need to specify two things, the
  1167. filename and the DOS file access mode. If the open succeeds, the DOS file
  1168. handle is returned. Use this handle for all further access to this file.
  1169. Each .DBF data file you open allocates 144+((1 + number of fields) * 32) bytes
  1170. for internal use. This memory is not deallocated until you close the file with
  1171. CloseDXB or execute ExitXB.
  1172. You must open the data file before you can open (or create) any of its index
  1173. files.
  1174. See: CloseDXB  OpenKXB
  1175. ~CloseDXB
  1176. Pack: HandlePack        Src: CloseDXBsrc        Func:  12/Mid-level
  1177. Close an existing .DBF data file for use. Closing the file updates the file
  1178. header and deallocates the memory used by this file.
  1179. You MUST close all BULLET files before ending your program or file corruption
  1180. may occur. To ensure that all files are closed in the event of an unscheduled
  1181. program termination, use AtExitXB.                                           
  1182. See: StatDXB  ExitXB  CloseKXB
  1183. ~StatDXB
  1184. Pack: StatDataPack      Src: StatDXBsrc         Func:  13/Mid-level
  1185. Get basic information on the BULLET .DBF data file handle specified.
  1186. Information returned includes the number of records in the file, the record
  1187. length, number of fields per record, and the date the file was last updated.
  1188. Typically, your program will keep track of whether a particular handle belongs
  1189. to a data file or a key file. In cases where this is not possible, call the
  1190. StatHandleXB routine to determine what file type a handle is.
  1191. Note that a just-created data file will have the LastUpdate date set to 0/0/0.
  1192. See: ReadDHXB  StatKXB  StatHandleXB
  1193. ~ReadDHXB
  1194. Pack: HandlePack        Src: ReadDHXBsrc        Func:  14/Mid-level
  1195. Reload the disk copy of the data header for the opened .DBF data file handle
  1196. to the internal copy.
  1197. In single-user, single-tasking systems this routine is not needed. However, in
  1198. a multi-user or multi-tasking system it's possible, and desirable, for two or
  1199. more programs to use the same data file. Consider this scenario: A data file
  1200. has 100 records. Two programs access this data file, both opening it. Program 1
  1201. locks the file, adds a new record, then flushes and unlocks the file. Program 1
  1202. knows that there are now 101 records in the file. However, Program 2 is not
  1203. aware of the changes that Program 1 made--it thinks that there are still 100
  1204. records in the file. This out-of-sync situation is easily remedied by having
  1205. Program 2 reload the data header from the file on disk.
  1206. How does Program 2 know that it needs to reload the header? It doesn't. Instead
  1207. BULLET uses a simple yet effective approach when dealing with such problems.
  1208. Whenever your program locks a file, BULLET automatically reloads the header.
  1209. Whenever you unlock a file, BULLET automatically flushes the header.
  1210. See: FlushDHXB  ReadKHXB  LockXB
  1211. ~FlushDHXB
  1212. Pack: HandlePack        Src: FlushDHXBsrc       Func:  15/Mid-level
  1213. Write the internal copy of the data header for the opened .DBF data file handle
  1214. to disk. The actual write occurs only if the header has been changed.
  1215. This is to ensure that the data header on disk matches exactly the data header
  1216. that is being maintained by BULLET. Also, this routine updates the operating
  1217. system's directory entry for this file.
  1218. Assume the following: A data file with 100 records. Your program opens the data
  1219. file and adds 1 record. Physically, there are 101 records on disk. However, the
  1220. header image of the data file on disk still reads 100 records. This isn't a
  1221. problem, BULLET uses its internal copy of the data header and the internal copy
  1222. does read 101 records. BUT, if there were a system failure now, the disk image
  1223. would not get updated. After the system restart, BULLET opens the file, reads
  1224. the header and thinks that there are 100 records. You lost a record. Now, if
  1225. after that add above, your program issued a FlushDHXB, the header on disk is
  1226. refreshed with the internal copy, keeping the two in-sync. Also, the routine
  1227. updates the DOS directory entry, keeping things neat there as well. Still, it
  1228. doesn't come without cost: flushing will take additional time, therefore, you
  1229. may elect to flush periodically, or whenever the system is idle.
  1230. See: CopyDHXB  ReadDHXB  FlushKHXB  LockXB
  1231. ~CopyDHXB
  1232. Pack: CopyPack          Src: CopyDHXBsrc        Func:  16/Mid-level
  1233. Copy the .DBF file structure of an open data file to another DOS file.
  1234. This routine makes it easy for you to duplicate the structure of an existing
  1235. .DBF file without having to specify all the information needed by CreateDXB.
  1236. The resultant .DBF will be exactly like the source, including number of fields
  1237. and field descriptions. It will contain 0 records.
  1238.      
  1239. See: ZapDHXB  CopyDHXB
  1240. ~ZapDHXB
  1241. Pack: HandlePack        Src: ZapDHXBsrc         Func:  17/Mid-level
  1242. Delete all records for a .DBF data file.
  1243. This routine is similar to CopyDHXB except for one major difference: ALL DATA
  1244. RECORDS IN THE *SOURCE* FILE ARE PHYSICALLY DELETED, so be *careful*.
  1245. If you have a .DBF file with 100 records and use ZapDHXB on it, all 100 records
  1246. will be physically deleted and the file truncated to 0 records. There is no
  1247. return from this routine. All data is gone.
  1248.                            
  1249.                            
  1250. * C A U T I O N *
  1251.                            
  1252.      
  1253. See: CreateKXB  CopyDHXB  ZapKHXB
  1254. ~CreateKXB
  1255. Pack: CreateKeyPack     Src: CreateKXBsrc       Func:  20/Mid-level
  1256. Create a new BULLET key file. Before you can create a key file, you must first
  1257. have opened (and have created if necessary) the BULLET .DBF data file that it
  1258. is to index. (BULLET couples index and data files tightly.)
  1259. To create the key file, you need to provide the key expression, key flags, .DBF
  1260. file link handle, and optionally, the code page ID, country code, and collate
  1261. table.
  1262.                                 Key Expression
  1263. The key expression is an ASCII character string composed of the elements that
  1264. are to make up this index file's key. The key can be composed of any or all of
  1265. the fields in the .DBF data record or sub-strings within any of those fields.
  1266. Two functions are supported in evaluating a key expression. These are SUBSTR()
  1267. and UPPER(). SUBSTR() extracts part of a string starting at a particular
  1268. position for x number of characters. UPPER() converts all lower-case letters to
  1269. their upper-case equivalent. Since BULLET supports NLS, UPPER() conversion is
  1270. not required for proper sorting of mixed-case text strings.
  1271. See: CreateKXB_a  CreateDXB                                             -MORE-
  1272. ~CreateKXB_a
  1273. All names used in the key expression must be a valid field name in the DBF data
  1274. file. Some sample key expressions given that the .DBF has the following fields:
  1275.  Fields...             Valid key expressions
  1276.      
  1277.  FNAME C 25 0       "LNAME"            (all must be 0-terminated)
  1278.  LNAME C 25 0       "LNAME+FNAME"
  1279.  SSN   C  9 0       "SUBSTR(LNAME,1,4)+SUBSTR(FNAME,1,1)+SUBSTR(SSN,6,4)"
  1280.  DEPT  N  5 0       "UPPER(LNAME+FNAME)"  (for non-NLS index files)
  1281.   :     :           "DEPT+SSN" (N- + C-type is valid for non-binary keys)
  1282.                                     Key Flags
  1283. The key expression is used in conjunction with the key flags to determine the
  1284. type of key generated.
  1285. First, if your index file is to disallow duplicate keys, add 1 to KeyFlag.
  1286. If you have a key composed of a character field(s) or portions thereof, you
  1287. specify a KeyFlag = 2. This instructs BULLET that the sort order is left-to-
  1288. right (proper mixed-case sorting is available, see code page ID).
  1289. See: CreateKXB_b                                                        -MORE-
  1290. ~CreateKXB_b
  1291. If you have a key composed of a numeric field(s) or portions thereof, you can
  1292. also specify a KeyFlag = 2. This instructs BULLET to treat the numeric field
  1293. as a regular character field for sorting. To ensure proper sorting, you must
  1294. decimal-align the +numeric strings in the .DBF data field, i.e., right-justify
  1295. the numeric strings (dBASE .DBF numeric strings are stored as ASCII strings).
  1296. These non-binary numeric fields are just like character fields to BULLET.
  1297. In addition, if you have a key composed of a SINGLE numeric field (fld type N)
  1298. and the field is an integer (NO DECIMAL POINT), you can specify a KeyFlag of 16
  1299. or 32. KeyFlag=16 is for a field known to be in word/integer range; KeyFlag=32
  1300. if the field is known to be in LongInt range. These KeyFlag values instruct
  1301. BULLET to sort the key as a 16/32-bit BINARY value. It also stores the key as a
  1302. 16- or 32-bit value (only 2 or 4 bytes) in the index, eventhough the data field
  1303. is in ASCII (keyflag=16 or 32).
  1304. Although not dBASE compatible, you may use BINARY FIELDS in your data records.
  1305. dBASE always has ASCII data in the data fields, even if the field is numeric.
  1306. For example, an N type field of 8.2 is stored as an ASCII text string in the
  1307. data record, say, a string like " 1100.55". If you want dBASE compatibility
  1308. your field data must also be ASCII. However, if you can forgo this requirement,
  1309. you can use binary values in the fields.
  1310. See: CreateKXB_c                                                        -MORE-
  1311. ~CreateKXB_c
  1312. To do this you must specify a field type of "B" (actually, anything but a "N")
  1313. and, IF IT IS TO BE USED AS A KEY FIELD, also set the 16- or 32-bit KeyFlag.
  1314. Unique and signed may also be flagged. The field length for a "B" field type is
  1315. 2 or 4. Make sure the key flags match (2 if cINTEGER, 4 if cLONG).
  1316. If you specify a binary key flag (for either N or B field types), you must also
  1317. specify whether the field is to be treated as a signed or unsigned value. If
  1318. values less than 0 are possible, add to KeyFlag the hex number 0x8000.
  1319.  KeyFlag = cUNIQUE|cCHAR;          /* unique character key (NLS sort)      */
  1320.  KeyFlag = cINTEGER|cUNIQUE;       /* unique unsigned integer (binary sort)*/
  1321.  KeyFlag = cUNIQUE|cSIGNED|cLONG;  /* unique signed long                   */
  1322.  KeyFlag = cCHAR;                  /* character key with duplicates allowed*/
  1323.  KeyFlag = cCHAR|cINTEGER;         /* THIS IS AN INVALID KEY FLAGS!        */
  1324. The following values are defined in BULLET.H:
  1325.   cUNIQUE=1, cCHAR=2, cINTEGER=0x10, cLONG=0x20, cNLS=0x4000, cSIGNED=0x8000
  1326. The NLS flag is assigned by BULLET. StatKXB is used to query KeyFlags.
  1327. See: CreateKXB_d                                                        -MORE-
  1328. ~CreateKXB_d
  1329. The key expression you specify may be up to 136 characters, and evaluate out to
  1330. 64 bytes (62 bytes if unique key is not specified). I.e, "SUBSTR(..." can
  1331. be up to 136 characters, and that the actual key built from this expression can
  1332. be no longer that 64 bytes, or 62 if you did not specify UNIQUE. In general,
  1333. shorter keys (the key itself, not the expression) offer better performance.
  1334.                          DBF File Link Handle (XBlink)
  1335. Since BULLET evaluates the key expression at CreateKXB, it must have access to
  1336. the DBF file to verify that the key expression is valid. You must therefore
  1337. supply CreateKXB with the OS file handle of the opened DBF data file.
  1338. National Language Support (NLS)
  1339. With DOS 3.3 and later, NLS is available. BULLET uses NLS to build the collate
  1340. sequence table that it uses to ensure proper sorting of mixed-case keys as well
  1341. as the sorting of foreign language alphabets. In order for BULLET to use the
  1342. proper collate table, it must know what code page ID and coutry code to use.
  1343. This table is made part of the index file so that all subsequent access to the
  1344. index file maintains the original sort order, even if the MIS shop is moved to
  1345. another location/computer system using another country code/code page.
  1346. See: CreateKXB_e                                                        -MORE-
  1347. ~CreateKXB_e
  1348.                                 Code Page ID
  1349. To use the default code page ID of the computer in use, specify a code page ID
  1350. of -1. This instructs BULLET to use the collate-sequence table as provided by
  1351. MS-DOS running on the machine. You may also specify the code page ID for BULLET
  1352. to use, but only if support for the code page ID is available on your machine.
  1353. Look in your DOS manual under CUSTOMIZING FOR INTERNATIONAL USE for specific
  1354. code page IDs and country codes. See also the COUNTRY and NLSFUNC commands.
  1355. You may also specify a code page ID = 0 in which case no collate table is used.
  1356.                                 Country Code
  1357. To use the default country code of the computer in use, specify a country code
  1358. of -1. This instructs BULLET to use the collate-sequence table as provided by
  1359. MS-DOS running on the machine. You may also specify the country code for BULLET
  1360. to use, but only if support for the country code is available on your machine.
  1361. Look in your DOS manual under CUSTOMIZING FOR INTERNATIONAL USE for specific
  1362. code page IDs and country codes. See also the COUNTRY and NLSFUNC commands.
  1363. You may also specify a country code = 0 in which case no collate table is used.
  1364. Typically, you set CodePageID = -1, CoutryCode = -1 and CollatePtr = 0.
  1365. See: CreateKXB_f                                                        -MORE-
  1366. ~CreateKXB_f
  1367.                          User-specified Collate Table
  1368. If you are to use a MS-DOS supplied collate table (BOTH codepage ID and country
  1369. codes are non-zero) then you do not need to specify a collate table--DOS will.
  1370. The option to allow a user-specified collate table is to work around some DOS
  1371. versions supplying incorrect collate tables. If you find that the DOS-supplied
  1372. collate table is not valid (it's stored in the second sector of the file) for
  1373. your country, you can supply the table to be used by pointing the CollatePtr
  1374. variables to your in-memory version of a valid collate table. If you want to
  1375. use the DOS-supplied collate table, you MUST set the CollatePtr variables = 0.
  1376. Note: The collate table is a 256-byte table that contains the sort value of
  1377. each character (0-255). For example, the first byte would be 0, second would
  1378. be 1, and so on. Values for characters up to the lower-case letters (ASCII 97)
  1379. are usually as you would expect: "A" has a value of 65. However, the lower-case
  1380. letters have the same value as their upper-case counterparts: "a" also has a
  1381. value of 65. BULLET uses this collate table to ensure proper sorting.
  1382. If you specify EITHER code page ID OR country code = 0 then no collate table
  1383. is used or built. Instead, sorting is done by standard ASCII sort. This is
  1384. somewhat faster but less versatile. Use UPPER() for mixed-case sort if needed.
  1385. See: OpenKXB  CreateKXB
  1386. ~OpenKXB
  1387. Pack: OpenPack          Src: OpenKXBsrc         Func:  21/Mid-level
  1388. Open an existing key file for use.
  1389. Each key file that you open allocates 1264 bytes for internal use. This memory
  1390. is not deallocated until you close the file with CloseKXB or execute ExitXB.
  1391. You must open the data file before you can open its related index file
  1392. because you must supply the handle of the data file that this index files
  1393. indexes.
  1394. See: CloseKXB  OpenDXB
  1395. ~CloseKXB
  1396. Pack: HandlePack        Src: CloseKXBsrc        Func:  22/Mid-level
  1397. Close an open key file. Closing the file updates the file header and
  1398. deallocates the memory used by this file.
  1399. You MUST close all BULLET files before ending your program or file corruption
  1400. may occur. To ensure that all files are closed on the event of an unscheduled
  1401. program termination, use AtExitXB.                                           
  1402. See: StatKXB  ExitXB  CloseDXB
  1403. ~StatKXB
  1404. Pack: StatKeyPack       Src: StatKXBsrc         Func:  23/Mid-level
  1405. Get basic information on a BULLET key file handle specified. Information
  1406. returned includes the number of keys in the file, the key length, the data file
  1407. handle for this key, the last accessed record number of that data file, NLS
  1408. information, and the key flags.
  1409. Typically, your program will keep track of whether a particular handle belongs
  1410. to a key file or a data file. In cases where this is not possible, call the
  1411. StatHandleXB routine to determine what file type a handle is.
  1412. See: ReadKHXB  StatDXB  StatHandleXB
  1413. ~ReadKHXB
  1414. Pack: HandlePack        Src: ReadKHXBsrc        Func:  24/Mid-level
  1415. Reload the disk copy of the key header for the opened key file handle to the
  1416. internal copy.
  1417. In single-user, single-tasking systems this routine is not needed. However, in
  1418. a multi-user or multi-tasking system it's possible, and desirable, for two or
  1419. more programs to use the same data file. Consider this scenario: A key file has
  1420. 100 keys. Two programs access this key file, both opening it. Program 1 locks
  1421. the file, adds a new key, then flushes and unlocks the file. Program 1 knows
  1422. that there are now 101 keys in the file. However, Program 2 is not aware of the
  1423. changes that Program 1 made--it thinks that there are still 100 keys in the
  1424. file. This out-of-sync situation is easily remedied by having Program 2 reload
  1425. the key header from the file on disk.
  1426. How does Program 2 know that it needs to reload the header? It doesn't. Instead
  1427. BULLET uses a simple yet effective approach when dealing with such problems.
  1428. Whenever your program locks a file, BULLET automatically reloads the header.
  1429. Whenever you unlock a file, BULLET automatically flushes the header.
  1430. See: FlushKHXB  ReadDHXB  FlushDHXB  LockXB
  1431. ~FlushKHXB
  1432. Pack: HandlePack        Src: FlushKHXBsrc       Func:  25/Mid-level
  1433. Write the internal copy of the key header for the opened key file handle to
  1434. disk. The actual write occurs only if the header has been changed.
  1435. This is to ensure that the key header on disk matches exactly the key header
  1436. that is being maintained by BULLET. Also, this routine updates the operating
  1437. system's directory entry for this file.
  1438.      
  1439. Assume the following: A data file with 100 keys. Your program opens the key
  1440. file and adds 1 key. Physically, there are 101 keys on disk. However, the
  1441. header image of the data file on disk still reads 100 keys. This isn't a
  1442. problem, BULLET uses its internal copy of the key header and the internal copy
  1443. does read 101 keys. BUT, if there were a system failure now, the disk image
  1444. would not get updated. After the system restart, BULLET opens the file, reads
  1445. the header and thinks that there are 100 keys. You lost a key. Now, if after
  1446. that add above, your program issued a FlushKHXB, the header on disk is
  1447. refreshed with the internal copy, keeping the two in-sync. Also, the routine
  1448. updates the DOS directory entry, keeping things neat there as well. Still, it
  1449. doesn't come without cost: flushing will take additional time, therefore, you
  1450. may elect to flush periodically, or whenever the system is idle.
  1451. See: CopyKHXB  ReadKHXB  FlushKHXB  LockXB
  1452. ~CopyKHXB
  1453. Pack: CopyPack          Src: CopyKHXBsrc        Func:  26/Mid-level
  1454. Copy the key file structure of an open key file to another DOS file.
  1455. This routine makes it easy for you to duplicate the structure of an existing
  1456. key file without having to specify all the information needed by CreateKXB.
  1457. The resultant key file will be exactly like the source, including key flags and
  1458. key expression. It will contain 0 keys.
  1459.      
  1460. See: ZapKHXB  CopyKHXB
  1461. ~ZapKHXB
  1462. Pack: HandlePack        Src: ZapKHXBsrc         Func:  27/Mid-level
  1463. Delete all keys for a key file.
  1464. This routine is similar to CopyKHXB except for one major difference: ALL KEYS
  1465. IN THE *SOURCE* FILE ARE PHYSICALLY DELETED, so be *careful*.
  1466. If you have a key file with 100 keys and use ZapKHXB on it, all 100 keys will
  1467. be physically deleted and the file truncated to 0 keys. There is no return from
  1468. this routine. All data is gone.
  1469.                            
  1470.                            
  1471. * C A U T I O N *
  1472.                            
  1473.      
  1474. See: GetDescriptorXB  CopyKHXB  ZapDHXB
  1475. ~GetDescriptorXB
  1476. Pack: DescriptorPack    Src: GetDescriptorXBsrc Func:  30/Mid-level
  1477. Get the field descriptor information for a field.
  1478. You can specifiy either the fieldname or the field number (position of the
  1479. field within the record where the first field is #1) to get info on.
  1480. The field descriptor contains the following information:
  1481.   FIELDNAME  10 upper-case characters, A-Z and _ allowed, unused space is
  1482.              0-filled and is 0-terminated (11 bytes, ASCII, byte 11 always=0)
  1483.   FIELDTYPE  single ASCII character where C=character, N=numeric, D=date,
  1484.              L=logical, and M=memo field (1 byte, ASCII)
  1485.   FIELDLEN   length of field: C=1-254, N=1-19, D=8 (yyyymmdd), L=1 (T/F/space),
  1486.              M=10, this is total field length (1 byte, binary)
  1487.   FIELDDC    places right of decimal point if N field type, minimum if not 0 is
  1488.              2, can be up to 6 or 8, non-N fields always 0 (1 byte, binary)
  1489. See: GetRecordXB
  1490. ~GetRecordXB
  1491. Pack: AccessPack        Src: GetRecordXBsrc     Func:  31/Mid-level
  1492. Get the physical record from the data file into a data buffer by record number.
  1493. The data buffer is typically a struct variable defined as the DBF record itself
  1494. is defined. For example, if the DBF record has 2 fields, LNAME and FNAME, then
  1495. variable would be struct'ed as:
  1496. struct rectype {
  1497.         char  tag;           /* The Xbase DBF delete flag (must be included) */
  1498.         char  lastname[25];  /* same field length as the .DBF LNAME field    */
  1499.         char  firstname[25]; /* same field length as the .DBF FNAME field    */
  1500. }; /* 51 */
  1501. struct rectype recbuff;
  1502. This method of accessing the data file does not use any indexing. Therefore, it
  1503. typically is not used except for special purposes. The preferred method to
  1504. access the data is by one of the keyed Get() routines.
  1505. See: AddRecordXB  GetEqualXB
  1506. ~AddRecordXB
  1507. Pack: AccessPack        Src: AddRecordXBsrc     Func:  32/Mid-level
  1508. Append the record in the data buffer to the end of the DBF file.
  1509. This method of adding a record does not involve any indexing. It is typically
  1510. used to build a data file en masse and do the indexing after the entire .DBF 
  1511. file(s) has been built.                                                      
  1512. If you have several thousand data records to be added at once, this method of
  1513. building the DBF first and then using the ReindexXB routine is often faster
  1514. than using the InsertXB routine for each record to add.
  1515. The AddRecordXB is very fast. 400 recs/sec on an AT machine is typical. Over
  1516. 2000 recs/sec can be added on a fast 486 machine--that's 120,000 records added
  1517. per minute.
  1518. The record number used is determined by BULLET and it is returned in AP.RecNo.
  1519. See: UpdateRecordXB  InsertXB  ReindexXB
  1520. ~UpdateRecordXB
  1521. Pack: AccessPack        Src: UpdateRecordXBsrc  Func:  33/Mid-level
  1522. Write the updated data record to the the physical record number.
  1523. This method of writing the updated record must not be used if any field(s) in
  1524. the record is used as a key field(s) and has been changed.                   
  1525. This method of updating a record is very fast if you know that that update is
  1526. not going to alter any field used as a key in any index file that uses it. You
  1527. must, of course, first get the data record into the record buffer. Then you can
  1528. change it and write the update out to disk with this routine.
  1529. If you need to change a field(s) that is used as a key field or part of one,
  1530. use the UpdateXB routine. UpdateXB not only dynamically updates all related
  1531. index files if you change a key field, it also will undo any and all changes if
  1532. an error occurs in the transaction.
  1533. See: DeleteRecordXB  GetRecordXB  UpdateXB
  1534. ~DeleteRecordXB
  1535. Pack: AccessPack        Src: DeleteRecordXBsrc  Func:  34/Mid-level
  1536. Tag the record at the physical record number as being deleted.
  1537. This does not tag any in-memory copies of the record so be sure to mark any
  1538. such copies as being deleted yourself.                                     
  1539. The first byte of every .DBF record is reserved for the delete tag. This tag
  1540. is a space (ASCII 32) if the record is normal, or a * (ASCII 42) if it's marked
  1541. as being deleted. This delete tag is a reserved field in the DBF record and as
  1542. such is not defined as a formal field with a descriptor, etc. Make sure that
  1543. you define your in-memory buffers to reserve the first byte for the delete tag.
  1544. The Xbase DBF standard doesn't physically remove records marked as deleted from
  1545. the data file. It doesn't mark them as available/reusable either. To physically
  1546. remove records marked as deleted use PackRecordsXB.
  1547. Records can be temporarily marked as deleted then recalled to normal status.
  1548. The Key/Get routines (GetFirstXB, etc.) return the record number needed for
  1549. this routine after each access in AP.RecNo.
  1550. See: UndeleteRecordXB  PackRecordsXB
  1551. ~UndeleteRecordXB
  1552. Pack: AccessPack        Src: UndeleteRecordsrc  Func:  35/Mid-level
  1553. Tag the record at the physical record number as being normal (not deleted).
  1554. This does not tag any in-memory copies of the record so be sure to mark any
  1555. such copies as being normal yourself.                                      
  1556. The first byte of every .DBF record is reserved for the delete tag. This tag
  1557. is a space (ASCII 32) if the record is normal, or a * (ASCII 42) if it's marked
  1558. as being deleted. This delete tag is a reserved field in the DBF record and as
  1559. such is not defined as a formal field with a descriptor, etc. Make sure that
  1560. you define your in-memory buffers to reserve the first byte for the delete tag.
  1561. The Xbase DBF standard does not physically remove records marked as deleted
  1562. from the data file so you can "recall" then back to normal status as easily as
  1563. you marked them deleted.
  1564. See: PackRecordsXB  DeleteRecordXB
  1565. ~PackRecordsXB
  1566. Pack: AccessPack        Src: PackRecordsXBsrc   Func:  36/Mid-level
  1567. Rebuild the open DBF file by physically removing all records marked as deleted.
  1568. Packing occurs in place using the existing file. It's recommended that you   
  1569. use BackupFileXB to copy the current DBF file before using this routine in   
  1570. case of a failure during the pack process.                                   
  1571. The newly packed file is truncated to reflect the current, actual size.
  1572. If there are index files for this .DBF file, they MUST all be reindexed after
  1573. the pack process by using ReindexXB.
  1574. This routine dynamically allocates at least as many bytes as the length of   
  1575. the record. More if available.                                               
  1576. See: FirstKeyXB  DeleteRecordXB  BackupFileXB  ReindexXB
  1577. ~FirstKeyXB
  1578. Pack: AccessPack        Src: FirstKeyXBsrc      Func:  40/Mid-level
  1579. Retrieve the first key in index order from the index file.
  1580. This routine does not access the .DBF file and so does not retrieve the data 
  1581. record. What it does do is locate the first key of the index, returning it,  
  1582. and also returning the record number within the .DBF that the key indexes.   
  1583. To retrieve the data record you can use the GetRecordXB routine. The preferred
  1584. method, however, is to use the GetFirstXB.
  1585. The key returned includes an enumerator if a non-unique index file is involved.
  1586. The enumerator is a little-endian 16-bit value that serves to differentiate  
  1587. up to 65535 "identical", non-unique keys. It is attached to all keys of non- 
  1588. unique index files and occupies the last two bytes of the key.               
  1589. This routine is typically used to position the index file to the first key so
  1590. as to allow forward in-order access to the keys by using NextKeyXB.
  1591. See: EqualKeyXB  GetFirstXB  GetRecordXB
  1592. ~EqualKeyXB
  1593. Pack: AccessPack        Src: EqualKeyXBsrc      Func:  41/Mid-level
  1594. Search for the exact key in the index file.
  1595. This routine does not access the .DBF file and so does not retrieve the data 
  1596. record. What it does do is search for the key in the index, and if found,    
  1597. returns the record number within the .DBF that the key indexes. The key must 
  1598. be an exact match, including enumerator word if a non-unqiue index file.     
  1599. To retrieve the data record you can use the GetRecordXB routine. The preferred
  1600. method, however, is to use the GetEqualXB.
  1601. This routine will only find EXACT matches to the specified key (including the
  1602. enumerator if applicable). However, even if the exact key is not found in the
  1603. index file, the index file is positioned so that the next NextKeyXB retrieves
  1604. the key that would have followed the unmatched specified key. For example,
  1605. if the key to match was "KINGS" (a partial key in this case), EqualKeyXB would
  1606. return a key not found error. If you were to now do a NextKeyXB, the next key
  1607. would be returned, let's say it is "KINGSTON".  If index file is not unique,
  1608. you must append the enumerator bytes (\0\0 for the first, \0\1 next, ...).
  1609. See: NextKeyXB  GetEqualXB  GetRecordXB
  1610. ~NextKeyXB
  1611. Pack: AccessPack        Src: NextKeyXBsrc       Func:  42/Mid-level
  1612. Retrieve the next key in index order from the index file.
  1613. This routine does not access the .DBF file and so does not retrieve the data 
  1614. record. What it does do is retreive the next key of the index, returning it, 
  1615. and also returning the record number within the .DBF that the key indexes.   
  1616. To retrieve the data record you can use the GetRecordXB routine. The preferred
  1617. method, however, is to use the GetNextXB.
  1618. The key returned includes an enumerator if a non-unique index file is involved.
  1619. This routine is typically called after the index file has first been positioned
  1620. to a known key using either FirstKeyXB or EqualKeyXB, or after a previous
  1621. NextKeyXB or even PrevKeyXB. What it basically does is get the key following
  1622. the current key, and then make that key the new current key.
  1623. See: PrevKeyXB  GetNextXB  GetRecordXB
  1624. ~PrevKeyXB
  1625. Pack: AccessPack        Src: PrevKeyXBsrc       Func:  43/Mid-level
  1626. Retrieve the previous key in index order from the index file.
  1627. This routine does not access the .DBF file and so does not retrieve the data 
  1628. record. What it does do is retreive the previous key of the index, returning 
  1629. it and also returning the record number within the .DBF that the key indexes.
  1630. To retrieve the data record you can use the GetRecordXB routine. The preferred
  1631. method, however, is to use the GetPrevXB.
  1632. The key returned includes an enumerator if a non-unique index file is involved.
  1633. This routine is typically called after the index file has first been positioned
  1634. to a known key using either LastKeyXB or EqualKeyXB, or after a previous
  1635. PrevKeyXB or even NextKeyXB. What it basically does is to get the key previous
  1636. the current key, and then make that key the new current key.
  1637. See: LastKeyXB  GetPrevXB  GetRecordXB
  1638. ~LastKeyXB
  1639. Pack: AccessPack        Src: LastKeyXBsrc       Func:  44/Mid-level
  1640. Retrieve the last key in index order from the index file.
  1641. This routine does not access the .DBF file and so does not retrieve the data 
  1642. record. What it does do is locate the last key of the index, returning it,   
  1643. and also returning the record number within the .DBF that the key indexes.   
  1644. To retrieve the data record you can use the GetRecordXB routine. The preferred
  1645. method, however, is to use the GetLastXB.
  1646. This routine is typically used to position the index file to the last key so as
  1647. to allow reverse in-order access to the keys by using PrevKeyXB.
  1648. See: StoreKeyXB  GetLastXB  GetRecordXB
  1649. ~StoreKeyXB
  1650. Pack: AccessPack        Src: StoreKeyXBsrc      Func:  45/Mid-level
  1651. Insert the key into the index file in proper key order.
  1652. This routine does not add the data record to the .DBF file. It only inserts  
  1653. the key and record number into the index file. Use InsertXB, instead.        
  1654. To do a complete data record and key insert, you could use AddRecordXB to add
  1655. the data record to the .DBF, BuildKeyXB to construct the key, then StoreKeyXB
  1656. to insert the key and record number information into the index file. If that
  1657. key already exists and the file allows duplicate keys, you need to attach the
  1658. proper enumerator word and retry StoreKeyXB.
  1659. This is much too much to do. Instead, just use InsertXB. All these details
  1660. including adding the data record and multi-key inserts are performed
  1661. automatically with just the single call.
  1662. See: DeleteKeyXB  InsertXB
  1663. ~DeleteKeyXB
  1664. Pack: AccessPack        Src: DeleteKeyXBsrc     Func:  46/Mid-level
  1665. Physically remove the specified key from the index file.
  1666. This routine requires an EXACT key match for all bytes of the key, including 
  1667. the enumerator word if a non-unique index file is involved.                  
  1668. This routine would seldom be used, typically, since deleted dBASE data records
  1669. are only physically deleted during a PackRecordsXB and the index file is
  1670. rebuilt afterward using ReindexXB.
  1671. See: BuildKeyXB  CurrentKeyXB
  1672. ~BuildKeyXB
  1673. Pack: AccessPack        Src: BuildKeyXBsrc      Func:  47/Mid-level
  1674. Build the key for the specifed data record based on the key expression for the
  1675. index file. If the index file is non-unique, a 0-value enumerator is attached.
  1676. The enumerator is a little-endian 16-bit value that serves to differentiate  
  1677. up to 65535 "identical", non-unique keys. It is attached to all keys of non- 
  1678. unique index files and occupies the last two bytes of the key.               
  1679. This routine, like most of the mid-level routines, typically would not be used
  1680. since the high-level access routines take care of this detail automatically.
  1681. Note: Little-endian in Bullet means that bit-order is from high to low.
  1682. Sometimes called Motorola format.  The first byte is of higher order than
  1683. the second, so \0\0 precedes \0\1 (then \0\2... \1\0, \1\1, \1\2, (so on)).
  1684. See: CurrentKeyXB  StoreKeyXB
  1685. ~CurrentKeyXB
  1686. Pack: AccessPack        Src: CurrentKeyXBsrc    Func:  48/Mid-level
  1687. Retrieve the current key value for the specified key file handle and also the
  1688. data record number that it indexes.
  1689. This routine is useful in that it retrieves on demand the actual key value of
  1690. the last accessed key in the index file (and the data record number). Most
  1691. often you don't need this information so it would be a waste of time and space
  1692. for your program to explicitly track each current key for each index file that
  1693. you have open.
  1694. See: GetFirstXB  ReindexXB  DeleteKeyXB
  1695. ~GetFirstXB
  1696. Pack: AccessPack        Src: GetFirstXBsrc      Func:  60/High-level
  1697. Retrieve the first indexed key and data record.
  1698. The key returned includes an enumerator if a non-unique index file is involved.
  1699. This routine is typically used to process a database in index order starting at
  1700. the first ordered key (and its data record). After processing this first entry,
  1701. subsequent in-order access of the database is achieved by using GetNextXB until
  1702. the end of the database is reached.
  1703. This routine, like all the high-level Get routines, fills in the AP.RecNo of
  1704. the record accessed. In GetFirstXB's case, it fills AP.RecNo with the record
  1705. number pointed to by the first key. Since this is so, the AP pack is primed for
  1706. an UpdateXB after each high-level Get. Other methods to get the record number
  1707. are to use CurrKeyXB or any of the Key routines (KeyFirstXB, etc.).
  1708. See: GetEqualXB  FirstKeyXB  UpdateXB
  1709. ~GetEqualXB
  1710. Pack: AccessPack        Src: GetEqualXBsrc      Func:  61/High-level
  1711. Search for the exact key in the index file and return its data record.
  1712. This routine will only find EXACT matches to the specified key (including the
  1713. enumerator if applicable). However, even if the exact key is not found in the
  1714. index file, the index file is positioned so that the next GetNextXB retrieves
  1715. the key that would have followed the unmatched specified key. For example,
  1716. if the key to match was "KINGS" (a partial key in this case), GetEqualXB would
  1717. return a key not found error. If you were to now do a GetNextXB, the next key
  1718. and data record would be returned, let's say the key is "KINGSTON" and its data
  1719. record is the data record for that key. Another GetNextXB would retrieve the
  1720. key and record after that. (GetPrevXB can be used in this fashion too.)
  1721. This routine, like all the high-level Get routines, fills in the AP.RecNo of
  1722. the record accessed. In GetEqualXB's case, it fills AP.RecNo with the record
  1723. number pointed to by the matched key. Since this is so, the AP pack is primed
  1724. for an UpdateXB after each high-level Get. Other methods to get the record
  1725. number are to use CurrKeyXB or any of the Key routines (KeyEqualXB, etc.).
  1726. See: GetNextXB  EqualKeyXB
  1727. ~GetNextXB
  1728. Pack: AccessPack        Src: GetNextXBsrc       Func:  62/High-level
  1729. Retrieve the next indexed key and its data record.
  1730. The key returned includes an enumerator if a non-unique index file is involved.
  1731. This routine is typically calld after the index file has first been positioned
  1732. to a known key using either GetFirstXB or GetEqualXB, or after a previous
  1733. GetNextXB or even GetPrevXB. What it basically does is get the key and data
  1734. record following the current key, and then make that key the new current key.
  1735. This routine, like all the high-level Get routines, fills in the AP.RecNo of
  1736. the record accessed. In GetNextXB's case, it fills AP.RecNo with the record
  1737. number pointed to by the next key. Since this is so, the AP pack is primed for
  1738. an UpdateXB after each high-level Get. Other methods to get the record number
  1739. are to use CurrKeyXB or any of the Key routines (KeyNextXB, etc.).
  1740. See: GetPrevXB  NextKeyXB
  1741. ~GetPrevXB
  1742. Pack: AccessPack        Src: GetPrevXBsrc       Func:  63/High-level
  1743. Retrieve the previous indexed key and record.
  1744. The key returned includes an enumerator if a non-unique index file is involved.
  1745. This routine is typically called after the index file has first been positioned
  1746. to a known key using either GetLastXB or GetEqualXB, or after a previous
  1747. GetPrevXB or even GetNextXB. What it basically does is to get the key and data
  1748. record previous the current key, and then make that key the new current key.
  1749. This routine, like all the high-level Get routines, fills in the AP.RecNo of
  1750. the record accessed. In GetPrevXB's case, it fills AP.RecNo with the record
  1751. number pointed to by the previous key. Since this is so, the AP pack is primed
  1752. for an UpdateXB after each high-level Get. Other methods to get the record
  1753. number are to use CurrKeyXB or any of the Key routines (KeyPrevXB, etc.).
  1754. See: GetLastXB  PrevKeyXB
  1755. ~GetLastXB
  1756. Pack: AccessPack        Src: GetLastXBsrc       Func:  64/High-level
  1757. Retrieve the last indexed key and record.
  1758. This routine is typically used to process a database in reverse index order
  1759. starting at the last ordered key (and its data record). After processing this
  1760. last entry, subsequent reverse-order access of the database is achieved by
  1761. using GetPrevXB until the top of the database is reached.
  1762. This routine, like all the high-level Get routines, fills in the AP.RecNo of
  1763. the record accessed. In GetLastXB's case, it fills AP.RecNo with the record
  1764. number pointed to by the last key. Since this is so, the AP pack is primed for
  1765. an UpdateXB after each high-level Get. Other methods to get the record number
  1766. are to use CurrKeyXB or any of the Key routines (KeyLastXB, etc.).
  1767. See: InsertXB  LastKeyXB
  1768. ~InsertXB
  1769. Pack: AccessPack        Src: InsertXBsrc        Func:  65/High-level
  1770. Add the data record to data file and insert the related key(s) into the linked
  1771. index file(s).
  1772. This routine is used to add new entries into a database, one at a time. The
  1773. data record is first added to the data file, then for each related index file,
  1774. a key is inserted into the appropriate index file. Up to 32 index files can be
  1775. automatically maintained for each data file.
  1776. This and several other routines are transaction-based. If a failure occurs
  1777. prior to the routine's completion, all changes made to the database by the
  1778. routine will be backed-out and the database (data and related index file(s))
  1779. effectively restored to its original state.
  1780.                                   
  1781. If the routine failed to complete, the function return value is the number of
  1782. the pack that caused the failure. The pack's Stat is checked to determine the
  1783. error code. If the function return value is 0, YOU MUST STILL check the first
  1784. pack's Stat. If it's non-zero, then the failure occured with the data record.
  1785. See: UpdateXB  StoreKeyXB
  1786. ~UpdateXB
  1787. Pack: AccessPack        Src: UpdateXBsrc        Func:  66/High-level
  1788. Modify an existing data record (identified by record number) and automatically
  1789. perform any index file updates needed to keep the index file(s) in sync.
  1790. If any key fields changed between the original record and the new one, this
  1791. routine updates the appropriate index file(s) by replacing the original key(s)
  1792. with new the key(s) based on the updated data record. Up to 32 index files can
  1793. be automatically maintained for each data file. Get routines (GetFirstXB, etc.)
  1794. set the AP.RecNo of the record that UpdateXB uses.
  1795. This and several other routines are transaction-based. If a failure occurs
  1796. prior to the routine's completion, all changes made to the database by the
  1797. routine will be backed-out and the database (data and related index file(s))
  1798. effectively restored to its original state.
  1799. If the routine failed to complete, the function return value is the number of
  1800. the pack that caused the failure. The pack's Stat is checked to determine the
  1801. error code. If the function return value is 0, YOU MUST STILL check the first
  1802. pack's Stat. If it's non-zero, then the failure occured with the data record.
  1803. See: ReindexXB  UpdateRecordXB
  1804. ~ReindexXB
  1805. Pack: AccessPack        Src: ReindexXBsrc       Func:  67/High-level
  1806. Reindex all related index files for a data file.
  1807. The index file(s) must already exist and be open. Any existing key data is
  1808. overwritten by the new key data. In other words, if you have a 10MByte index
  1809. file, ReindexXB uses the same file space building the news keys over the old.
  1810. This results in a less fragmented disk and also minimizes disk space needed.
  1811. You can also create a new, empty index file and reindex to that. This would be
  1812. useful, for instance, if you needed to create a temporary index file--something
  1813. that you'd use for a report, say, then delete after the report.
  1814. This routine creates a TEMPORARY work file in either the current directory or,
  1815. if the DOS environment variable TMP is defined, in the TMP= directory. The size
  1816. of this file is approx. bytes = (RECORDS * (KEYLEN+6)). ReindexXB can operate
  1817. in as little as 32K of available memory and can use up to 128K. The resultant
  1818. index file(s) are optimized for minimum size AND maximum retrieval speed.
  1819. If the routine failed to complete, the function return value is the number of
  1820. the pack that caused the failure. The pack's Stat is checked to determine the
  1821. error code. A return value of zero indicates no error occured.               
  1822. See: LockXB  PackRecordsXB
  1823. ~LockXB
  1824. Pack: AccessPack        Src: LockXBsrc          Func:  80/Network
  1825. Lock all bytes in the index file handle(s) for exclusive use by the current
  1826. process and reload the index file header(s) from disk. Also lock all bytes in
  1827. the related data file and reload the data file header from disk.
  1828. The files must have been opened with the appropriate share attribute and not 
  1829. in compatibility mode. SHARE.EXE MUST be installed or DOS error 1 is issued. 
  1830. This routine is transaction-based and will lock all index files specified in 
  1831. AccessPack and the data file. If any lock fails, all previous locks by this  
  1832. routine are released. The return value indicates which access pack failed, if
  1833. any. This value is used as the index into the AccessPack group for you to    
  1834. identify the error code. See LockXBsrc for determining this exactly.         
  1835. Use the DriveRemoteXB and/or FileRemoteXB to determine if locking is necessary.
  1836. If the files are on a remote drive then it is best to use locking. Locking may
  1837. also be necessary on multitasking local machines accessing shared files.
  1838. This routine is a combination of LockKeyXB and LockDataXB.
  1839. See: UnlockXB  LockKeyXB  LockDataXB  DriveRemoteXB  FileRemoteXB
  1840. ~UnlockXB
  1841. Pack: AccessPack        Src: UnlockXBsrc        Func:  81/Network
  1842. Unlock all bytes in the specified file handle(s) (previously locked) and flush
  1843. the file header(s) to disk (flush done before lock(s) released). Also unlock
  1844. all bytes in the related data file and flush the data file header to disk.
  1845. The files must have been opened with the appropriate share attribute and not 
  1846. in compatibility mode. SHARE.EXE MUST be installed or DOS error 1 is issued. 
  1847. This routine is transaction-based and will unlock all index files specified in
  1848. AccessPack and the data file. If an unlock fails the routine exits with a
  1849. return value indicating which access pack failed. This value is used as the
  1850. index into the AccessPack group for you to identify the error code. Note that
  1851. this routine does not attempt to re-lock those files unlocked successfully if
  1852. an error occurs in the transaction. If an error does occur (unlikely) you will
  1853. need to provide for unlocking the remaining files manually with the UnlockKeyXB
  1854. and UnlockDataXB routines. You should not rely on the operating system to
  1855. automatically unlock files when they're closed.
  1856. This routine is a combination of UnlockKeyXB and UnlockDataXB.
  1857. See: LockKeyXB  UnlockKeyXB  UnlockDataXB
  1858. ~LockKeyXB
  1859. Pack: AccessPack        Src: LockKeyXBsrc       Func:  82/Network
  1860. Lock all bytes in the index file handle(s) for exclusive use by the current
  1861. process and reload the index file header(s) from disk.
  1862. The files must have been opened with the appropriate share attribute and not 
  1863. in compatibility mode. SHARE.EXE MUST be installed or DOS error 1 is issued. 
  1864. This routine is transaction-based and will lock all index files specified in
  1865. AccessPack. If any lock fails, all previous locks by this routine are released.
  1866. The return value indicates which access pack failed, if any. This value is used
  1867. as the index into the AccessPack group for you to identify the error code.
  1868. The advantage of using region locks (LockKeyXB locks the entire file region) to
  1869. control file access is that the file does not need to be opened/closed using
  1870. the Deny Read/Write sharing attribute. Opening the file for Deny None, and
  1871. controlling subsequent access with region locks, allows for faster processing
  1872. since files do not need to be constantly opened and closed, as they would if
  1873. access were controlled by opening with Deny Read/Write.
  1874. See: UnlockKeyXB  LockXB
  1875. ~UnlockKeyXB
  1876. Pack: AccessPack        Src: UnlockKeyXBsrc     Func:  83/Network
  1877. Unlock all bytes in the specified file handle(s) (previously locked) and flush
  1878. the file header(s) to disk (flush done before lock(s) released).
  1879. The files must have been opened with the appropriate share attribute and not 
  1880. in compatibility mode. SHARE.EXE MUST be installed or DOS error 1 is issued. 
  1881. This routine is transaction-based and will unlock all index files specified in
  1882. AccessPack. If an unlock fails the routine exits with a return value indicating
  1883. which access pack failed. This value is used as the index into the AccessPack
  1884. group for you to identify the error code.
  1885. All file locks should be released when exclusive access in no longer needed. 
  1886. It is not recommended that you end your program without having released active
  1887. file locks. This is especially a valid concern for DOS versions prior to 5.0.
  1888. DOS 5 releases locks on files that are closed.
  1889. See: LockDataXB  UnlockXB
  1890. ~LockDataXB
  1891. Pack: AccessPack        Src: LockDataXBsrc      Func:  84/Network
  1892. Lock all bytes in the file handle's data file for exclusive use by the current
  1893. process and reload the data file header from disk. You must set AP.RecNo=0 to
  1894. do this. To lock a single record, set AP.RecNo=record# to lock.
  1895. The files must have been opened with the appropriate share attribute and not 
  1896. in compatibility mode. SHARE.EXE MUST be installed or DOS error 1 is issued. 
  1897. This routine locks the specified data file. If the handle specified is that of
  1898. an index file, that index file's related data file handle is used. For single-
  1899. record locks, AP.Handle must have a data file handle specified. Header loading
  1900. is not performed if locking a single record.
  1901. The advantage of using region locks (LockDataXB locks the entire file region)
  1902. to control file access is that the file does not need to be opened/closed using
  1903. the Deny Read/Write sharing attribute. Opening the file for Deny None, and
  1904. controlling subsequent access with region locks, allows for faster processing
  1905. since files do not need to be constantly opened and closed, as they would if
  1906. access were controlled by opening with Deny Read/Write.
  1907. See: UnlockDataXB
  1908. ~UnlockDataXB
  1909. Pack: AccessPack        Src: UnlockDataXBsrc    Func:  85/Network
  1910. Unlock all bytes in the specified file handle (previously locked) and flush the
  1911. data file header to disk (flush done before lock released). To do this you must
  1912. set AP.RecNo=0. To unlock a single record, set AP.RecNo=record# to unlock.
  1913. The files must have been opened with the appropriate share attribute and not 
  1914. in compatibility mode. SHARE.EXE MUST be installed or DOS error 1 is issued. 
  1915. This routine unlocks the specified data file. If the handle specified is that
  1916. of an index file that index file's related datafile handle is used. For single-
  1917. record unlocks, AP.Handle must have a data file handle specified. Flushing is
  1918. not performed if unlocking a single record.
  1919. All file locks should be released when exclusive access in no longer needed. 
  1920. It is not recommended that you end your program without having released active
  1921. file locks. This is especially a valid concern for DOS versions prior to 5.0.
  1922. DOS 5 releases locks on files that are closed.
  1923. See: DriveRemoteXB
  1924. ~DriveRemoteXB
  1925. Pack: RemotePack        Src: DriveRemoteXBsrc   Func:  86/Network
  1926. Determine if specified drive is remote (default drive=0, A:=1, B=2, C=3...).
  1927. This routine uses INT21/44/sub function 09.
  1928. In addition to returning the IsRemote state, this routine sends back the result
  1929. of the DX register and also the install state of SHARE.EXE.
  1930. The meaning of the bitflags in Flags are (where IsRemote=0):
  1931. Bit   Meaning drive...
  1932.  1   1=uses 32-bit sectoring
  1933.  6   1=accepts Generic IOCTL (for INT21/44/0D,0E,0Fh)
  1934.  7   1=accepts Query IOCTL Device (INT21/44/11h)
  1935.  9   1=is local but shared by other computers in the network
  1936. 11   1=accepts Does-Device-Use-Removable-Media (INT21/44/08)
  1937. 13   1=requires media descriptor in FAT
  1938. 14   1=accepts Receive/Send Control Data from Block Device (INT21/44/04,05)
  1939. 15   1=is Substitution drive (set by the DOS SUBST command)
  1940.      (all other bits=0)
  1941. See: FileRemoteXB  LockXB
  1942. ~FileRemoteXB
  1943. Pack: RemotePack        Src: FileRemoteXBsrc    Func:  87/Network
  1944. Determine if specified handle of file or device is remote.
  1945. This routine uses INT21/44/sub function 0Ah.
  1946. In addition to returning the IsRemote state, this routine sends back the result
  1947. of the DX register and also the install state of SHARE.EXE.
  1948. Flags bit 7=1 then handle is device, =0 then handle is file.
  1949. Bit   Meaning DEVICE...                 Bit   Meaning DEVICE...(cont)
  1950.  0   1=is console input device          13   1=is named pipe
  1951.  1   1=is console output device         15   1=is remote, 0=is local
  1952.  2   1=is null device                        (all other bits=0)
  1953.  3   1=is clock device                  Bit   Meaning FILE...
  1954.  4   1=is special device               0-5   xxxxxx=drive number (0=A...)
  1955.  5   1=is in binary mode, 0=in ASCII     6   1=has not been written to
  1956.  6   0=returns EOF if device is read    12   1=is NoInherit
  1957. 11   1=is network spooler               14   1=date/time not set at close
  1958. 12   1=is NoInherit                     15   1=is remote, 0=is local
  1959.                                              (all other bits=0)
  1960. See: SetRetriesXB  DriveRemoteXB  LockXB
  1961. ~SetRetriesXB
  1962. Pack: SetRetriesPack    Src: SetRetriesXBsrc    Func:  88/Network
  1963. Set the number of times DOS retries disk operations after a failure due to
  1964. file-sharing operations (locked file regions from LockXB routines).
  1965. This routine uses INT21/44/sub function 0Bh.
  1966. By default DOS retries an operation 3 times (without pausing between attempts)
  1967. before returning an error to the application.
  1968. If you change the default values it's recommended that the default state be  
  1969. restored before your application ends (Retries=3, Pause=1).                  
  1970. These values are pretty much determined by trial-and-error. You may find that
  1971. adding a delay between retries returns fewer access-denied errors, but on
  1972. current machines, the delay is in the few millisecond range, tops.
  1973. See: DeleteFileDOS  LockXB
  1974. ~DeleteFileDOS
  1975. Pack: DOSFilePack       Src: DeleteFileDOSsrc   Func: 100/DOS
  1976. Delete the specified file.
  1977. This routine uses DOS INT21/41 (interrupt 21h function 41h).
  1978. See: RenameFileDOS
  1979. ~RenameFileDOS
  1980. Pack: DOSFilePack       Src: RenameFileDOSsrc   Func: 101/DOS
  1981. Rename a file. May also be used to move the file to a new directory within the
  1982. partition.
  1983. This routine uses DOS INT21/56.
  1984. If the specified directory differs from the file's directory, the file's     
  1985. directory entry is moved to the new directory.                               
  1986. For example, if the FilenamePtr filename is C:\LP100\PROJ93A.INF and the
  1987. NewFilenamePtr filename is C:\ARCH\PROJ93A.INA, the file is essentially
  1988. renamed and also moved to the \ARCH directory.
  1989. See: CreateFileDOS
  1990. ~CreateFileDOS
  1991. Pack: DOSFilePack       Src: CreateFileDOSsrc   Func: 102/DOS
  1992. Create a new file.
  1993. This routine uses INT21/3C.
  1994. The specified filename/pathname must NOT already exist.
  1995. The file created is not left open. You must OpenFileDOS to use it.
  1996. The attribute used during the create can be:
  1997.   ATTRIBUTE       VALUE    MEANING
  1998.    Normal              0    normal access permitted to file
  1999.    Read-Only           1    read-only access permitted to file
  2000.    Hidden              2    file does not appear in directory listing
  2001.    System              4    file is a system file
  2002.    Volume              8    FILENAME used as volume label if no current label
  2003.    Archive            20h   file is marked for archiving
  2004. See: AccessFileDOS  OpenFileDOS
  2005. ~AccessFileDOS
  2006. Pack: DOSFilePack       Src: AccessFileDOSsrc   Func: 103/DOS
  2007. Determine if the specified file can be accessed with the specified
  2008. access/sharing mode.
  2009. This routine uses INT21/3D and INT21/3E.
  2010. Basically, a Does-File-Exist routine. It uses the specified access/sharing
  2011. attributes when trying to open the file. For example, if you specify
  2012. DFP.Attr = &H42 (R/W access + Deny None sharing) and use AccessFileDOS on a
  2013. Read-Only DOS file, the return value would be DOS error 5, Access Denied.
  2014. See: OpenFileDOS
  2015. ~OpenFileDOS
  2016. Pack: DOSFilePack       Src: OpenFileDOSsrc     Func: 104/DOS
  2017. Open the specified file with the specified access/sharing mode.
  2018. This routine uses INT21/3D.
  2019.   ACCESS          VALUE    MEANING
  2020.    Read-only           0    open for read-only access
  2021.    Write-only          1    open for write-only access
  2022.    Read/Write          2    open for read/write access
  2023.   SHARE
  2024.    Compatibility       0     any process may share file (not recommended)
  2025.    Deny Read/Write    10h    no other process may share file
  2026.    Deny Write         20h    no other process may share file for write
  2027.    Deny Read          30h    no other process may share file for read
  2028.    Deny None          40h    any process may share file except in Compatibilty
  2029.   INHERIT                                                                 mode
  2030.    NoInheritFlag      80h    if set child processes do not inherit file handles
  2031.                              (child process cannot inherit handle > 20)
  2032. The file access mode is a combination of ACCESS + SHARE + INHERIT.
  2033. See: SeekFileDOS  OpenPack
  2034. ~SeekFileDOS
  2035. Pack: DOSFilePack       Src: SeekFileDOSsrc     Func: 105/DOS
  2036. Position the DOS file pointer of the specified file to the specified position.
  2037. This routine uses INT21/42.
  2038. The position is a 32-bit value and is relative to either the start of the file,
  2039. the current file pointer position, or the end of the file.
  2040.  Method  Meaning
  2041.     0    start move from the start of file (offset is a 32-bit unsigned value)
  2042.     1    start move at the current position (offset a signed value)
  2043.     2    start move at the end of file (offset a signed value)
  2044. For example, to move to the 511th byte of a file (byte 0 being the first), set
  2045. the offset value to 511 and use Method 0. On return, the absolute offset value
  2046. of the new position is returned. This is useful with Method 2 since you can
  2047. specify an offset of 0 and have the file length returned.
  2048. Never position the file pointer to before the start of file.                 
  2049. See: ReadFileDOS
  2050. ~ReadFileDOS
  2051. Pack: DOSFilePack       Src: ReadFileDOSsrc     Func: 106/DOS
  2052. Read from the file or device the specified number of bytes into a buffer.
  2053. This routine uses INT21/3F.
  2054. On block devices (such as disks) input starts at the current file position and
  2055. the file pointer is repositioned to the last byte read +1.
  2056. It is possible to read less than the bytes specified without an error being  
  2057. generated. Compare the bytes to read with the returned bytes read value. If  
  2058. less then end of file was reached during the read, if 0 then file was at EOF.
  2059. By using DOS's predefined handles you can read from the keyboard (STDIN) by
  2060. using the STDIN handle, 0. The input will terminate after all specified bytes
  2061. have been read or after a CR (ASCII 0Dh). If more bytes are entered than were
  2062. requested, the next read will retrieve those excess bytes. Therefore, it's
  2063. suggested that you specify 129 bytes to input (DOS will process 127+CR/LF bytes
  2064. maximum when reading the STDIN device). Post-process the entered data by
  2065. scanning for the CR/LF.
  2066. See: ExpandFileDOS
  2067. ~ExpandFileDOS
  2068. Pack: DOSFilePack       Src: ExpandFileDOSsrc   Func: 107/DOS
  2069. Expands the specified file by the specified number of bytes.
  2070. This routine uses INT21/42 and INT21/40.
  2071. This routine is useful in pre-allocating disk space. By reserving disk space in
  2072. advance you can guarantee that enough disk space will be available for a future
  2073. operation (especially if more than 1 process is running). You'll also be able
  2074. ensure that the disk space that a file does use is as contiguous as possible.
  2075. Database systems are dynamic and their files typically allocate new space on
  2076. an as-needed basis. This dynamic allocation can cause parts of a file to be
  2077. located throughout the disk system, possibly affecting performance drastically.
  2078. By pre-allocating the disk space you can be assured of consistent throughput
  2079. performance since the file is contiguous.
  2080. See: WriteFileDOS
  2081. ~WriteFileDOS
  2082. Pack: DOSFilePack       Src: WriteFileDOSsrc    Func: 108/DOS
  2083. Write to the file or device the specified number of bytes from a buffer.
  2084. This routine uses INT21/40.
  2085. If the number of bytes written is less than the specified bytes, this routine
  2086. returns a -2 error code (or 65554 unsigned).                                 
  2087. On block devices (such as disk) output starts at the current file position, and
  2088. the file pointer is repositioned to the last byte written +1.
  2089. If the specified bytes to write is 0, the file is truncated at the current   
  2090. file pointer position.                                                       
  2091. By using DOS's predefined handles you can write to the screen (STDOUT) by
  2092. using the STDOUT handle, 1.
  2093. See: CloseFileDOS
  2094. ~CloseFileDOS
  2095. Pack: DOSFilePack       Src: CloseFileDOSsrc    Func: 109/DOS
  2096. Close the file flushing any internal buffers, releasing any locked regions, and
  2097. update the directory entry to the correct size, date, and time.
  2098. This routine uses INT21/3E.
  2099. If you have opened a file using the DOS open routine you should close it when
  2100. you no longer need it.
  2101. This routine can be used to close the predefined DOS handles (0-4) and make  
  2102. those handles available for reuse. Typically handles 0 and 1 should not be   
  2103. closed by an application since they are the STDIN and STDOUT that DOS uses   
  2104. for the current application (keyboard and screen).                           
  2105. Since BULLET provides for up to 250 user file handles for your applications it
  2106. isn't necessary for you to eek 3 more file handles by closing handles 2-4.
  2107. See: MakeDirDOS
  2108. ~MakeDirDOS
  2109. Pack: DOSFilePack       Src: MakeDirDOSsrc      Func: 110/DOS
  2110. Create a new subdirectory.
  2111. This routine uses INT21/39.
  2112. See: DeleteFileDOS
  2113. ~AccessPack
  2114.  Src: InsertXBsrc      Func: InsertXB and many more
  2115. struct AccessPack {  /* AP (AP is recommended pack name)
  2116.  unsigned  func;     /* varies                 >>>>> REFER to -BULLET.H- <<<<<
  2117.  unsigned  rstat;    /* ret:completion status      for current structure names
  2118.  unsigned  handle;   /* OS handle
  2119.  long      recNo;    /* in:rec# to get/delete/update (if applicable)
  2120.                      /* in:set to single rec# to lock or 0=lock all
  2121.                      /* ret:record number of data record accessed
  2122.  void  far *recPtr;  /* far pointer to record storage buffer
  2123.  void  far *keyPtr;  /* far pointer to search key buffer
  2124.  void  far *nextPtr; /* far pointer to next key access pack
  2125. }; /* 22 */          /* or 0:0 if end of link or if N/A
  2126. The NextPtr variables are only used by InsertXB, UpdateXB, ReindexXB, and the
  2127. LockXB routines. NextPtr is used as a link to the next related access pack,
  2128. if any. Not all entries are used by all routines. Generally, any routine that
  2129. gets/puts user data to the database uses this pack.
  2130. Note: Due to space limitations all comments should be assumed to be terminated
  2131. on the same line (implicit */).
  2132. See: BreakPack
  2133. ~BreakPack
  2134.  Src: BreakXBsrc       Func: BreakXB
  2135. struct BreakPack { /* BP
  2136.  unsigned  func;   /* 4
  2137.  unsigned  rstat;  /* ret:completion status
  2138.  unsigned  mode;   /* =0 disable Ctrl-C/Ctrl-Break, 1=restore
  2139. }; /* 6 */
  2140. A simple pack.
  2141. See: CopyPack
  2142. ~CopyPack
  2143.  Src: BackupFileXBsrc  Func: BackupFileXB, CopyDHXB, CopyKHXB
  2144. struct CopyPack {        /* CP
  2145.  unsigned  func;         /* 5=BackupFileXB,16=CopyDHXB,26=CopyKHXB
  2146.  unsigned  rstat;        /* ret:completion status
  2147.  unsigned  handle;       /* handle of BULLET file
  2148.  char far *filenamePtr;  /* far pointer to filenameZ
  2149. }; /* 10 */
  2150. See: CreateDataPack
  2151. ~CreateDataPack
  2152.  Src: CreateDXBsrc     Func: CreateDXB
  2153. struct CreateDataPack { /* CDP
  2154.  unsigned  func;        /* 10
  2155.  unsigned  rstat;       /* ret:completion status
  2156.  char far *filenamePtr; /* far pointer to filenameZ to create
  2157.  unsigned  noFields;    /* number of fields per record
  2158.  void far *fieldListPtr;/* far pointer to field list
  2159.  unsigned  fileID;      /* file signature byte, usually=3
  2160. }; /* 16 */
  2161. The FieldListPtr variables point to an array of struct fieldDescType. This
  2162. array is dimensioned for as many fields as there are in the record and contains
  2163. the field descriptors, one for each field.
  2164. See: CreateKeyPack  FieldDescType
  2165. ~CreateKeyPack
  2166.  Src: CreateKXBsrc     Func: CreateKXB
  2167. struct CreateKeyPack { /* CKP
  2168.  unsigned  func;       /* 20
  2169.  unsigned  rstat;      /* ret:completion status
  2170.  char far *filenamePtr;/* far pointer to filenameZ
  2171.  char far *keyExpPtr;  /* far pointer to key expressionZ
  2172.  unsigned  xbLink;     /* BULLET XB data handle this file indexes
  2173.  unsigned  keyFlags;   /* bit 0=unique,1=char,4=int,5=lng,F=signed
  2174.  int       codePageID; /* codepage for NLS, -1 use system default
  2175.  int       countryCode;/* country code for NLS, -1 to use default
  2176.  char far *collatePtr; /* far ptr to prg-supplied collate table
  2177. }; /* 24 */            /* or 0:0 if using sys-determined NLS table
  2178. Bit 14 in KeyFlags (0Eh) is set by BULLET during CreateKXB if a collate table
  2179. is present.
  2180. See: DescriptorPack  is_NLS
  2181. ~DescriptorPack
  2182.  Src: GetDescriptorXBsrc  Func: GetDescriptorXB
  2183. struct DescriptorPack {   /* DP
  2184.  unsigned  func;          /* 30
  2185.  unsigned  rstat;         /* ret:completion status
  2186.  unsigned  handle;        /* BULLET data file handle to get info on
  2187.  unsigned  fieldNumber;   /* field number to get info on, or if 0...
  2188.  struct fieldDescType fd; /* ...search for DP.FD.fieldName
  2189. }; /* 40 */
  2190. GetDescriptorXB allows you to get the field descriptor info for a particular
  2191. field number (as in the first field, or the 10th field, etc.) or, if you don't
  2192. know the physical field number, the routine can also get the info for a field
  2193. by field name.
  2194. To get the info for field number, say 5, set DP.FieldNumber = 5. The DP.FD
  2195. structure element is filled in with field 5's information.
  2196. To get the info for a field by fieldname, say LASTNAME, set dp.fieldnumber=0 &
  2197. strcpy(dp.fd.fieldname, "LASTNAME\0\0\0")--the fieldname must be zero-filled
  2198. and zero-terminated.
  2199. See: DOSFilePack  FieldDescType
  2200. ~DOSFilePack
  2201.  Src: AccessFileDOSsrc  Func: AccessFileDOS
  2202.                                             (all routines ending with DOS)
  2203. struct DosFilePack {   /* DFP
  2204.  unsigned  func;       /* varies, see DeleteFileDOS for first
  2205.  unsigned  rstat;      /* ret:completion status
  2206.  char far *filenamePtr;/* far pointer to filenameZ
  2207.  unsigned  handle;     /* in: handle to access  ret: handle opened
  2208.  unsigned  asMode;     /* open access/sharing mode
  2209.  unsigned  bytes;      /* in: bytes to read  ret: bytes read
  2210.  long      seekOffset; /* seek to file position
  2211.  unsigned  method;     /* seek method
  2212.  void far *bufferPtr;  /* far pointer to read/write buffer
  2213.  unsigned  attr;       /* file create directory entry attribute
  2214.  char far *newNamePtr; /* far pointer to new filenameZ for rename
  2215. }; /* 30 */
  2216. All of the xDOS routines use this pack. Often only a few of the structure
  2217. member elements are used by any one of the routines. Set only those needed.
  2218. See: DVmonPack
  2219. ~DVmonPack
  2220.  Src: DVmonCXBsrc      Func: DVmonCXB
  2221. struct DVmonPack { /* AVAILABLE ONLY IN THE DEBUG ENGINE
  2222.  unsigned  func;   /* 9
  2223.  unsigned  rstat;  /* ret:completion status
  2224.  unsigned  mode;   /* =0 disable montitoring, =1 enable
  2225.  unsigned  handle; /* file handle to monitor
  2226.  unsigned  vs;     /* segment to write screen image (e.g., 0xB800)
  2227. }; /* 10 */
  2228. This routine is supplied only in the BULLET debug engine. It displays real-time
  2229. monitoring information of a .DBF file or index and .DBF file pair including
  2230. searches, seeks, hits, current record number, current key, key node contents,
  2231. key node pointers, stack state, key and record counts, and other info.
  2232. See: ExitPack
  2233. ~ExitPack
  2234.  Src: InitXBsrc        Func: ExitXB, AtExitXB
  2235. struct ExitPack {  /* EP
  2236.  unsigned  func;   /* 1=ExitXB, 2=AtExitXB
  2237.  unsigned  rstat;  /* ret:completion status
  2238. }; /* 4 */
  2239. See: FieldDescType
  2240. ~FieldDescType
  2241.  Src: CreateDXBsrc     Func: CreateDXB
  2242. struct FieldDescType {   /* used by CreateDataPack ONLY
  2243.  char  fieldName[11];    /* 0-filled (use only ASCII 65-90,95)
  2244.  char  fieldType;        /* C-har,N-umeric,D-ate,L-ogical,M-emo
  2245.  unsigned long fieldDA;  /* =0,reserved
  2246.  unsigned char fieldLen; /* C=1-254,N=1-19(varies),D=8,L=1,M=10
  2247.  unsigned char fieldDC;  /* dec places for FieldType=N (0,2-15)
  2248.  long  fieldRez;         /* =0,reserved
  2249.  char  filler[10];       /* =0,reserved
  2250. }; /* 32 */
  2251. If you can can forgo dBASE compatility you can use the B field type. This type
  2252. is for fields that contain binary data (all dBASE fields contain ASCII text or
  2253. numeric strings). If you specify a fieldType = 'B' for, say an integer field,
  2254. use a FieldLen = 2. If the field is a long integer, use FieldLen = 4. You can
  2255. also use this non-standard field type for indexing. See CreateKXB for more.
  2256. See: HandlePack  CreateDataPack  CreateKXB
  2257. ~HandlePack
  2258.  Src: CloseDXBsrc      Func: CloseDXB, ReadDHXB, FlushDHXB, ZapDHXB
  2259.                              CloseKXB, ReadKHXB, FlushKHXB, ZapKHXB
  2260.                     /* HP
  2261. struct HandlePack { /* 12=CloseDXB,14=ReadDHXB,15=FlushDHXB,17=ZapDH
  2262.  unsigned  func;    /* 22=CloseDXB,24=ReadKHXB,25=FlushKHXB,27=ZapKH
  2263.  unsigned  rstat;   /* ret:completion status
  2264.  unsigned  handle;  /* handle of BULLET file
  2265. }; /* 6 */
  2266. See: InitPack
  2267. ~InitPack
  2268.  Src: InitXBsrc        Func: InitXB
  2269. struct InitPack {       /* IP
  2270.  unsigned  func;        /* 0
  2271.  unsigned  rstat;       /* ret:completion status
  2272.  unsigned  JFTmode;     /* expand JFT if non-zero
  2273.  unsigned  DOSver;      /* ret:DOS version (HB=major, LB=minor)
  2274.  unsigned  OSversion;   /* ret:BULLET OS version
  2275.                         /* (0=DOS, 1=Win16, 3=DOSX32, 4=OS/2, 5=Win32) */
  2276.  unsigned  version;     /* ret:BULLET version * 100 (120=1.20)
  2277.  unsigned long exitPtr; /* ret:far pointer to ExitXB routine
  2278. }; /* 14 */
  2279. See: MemoryPack
  2280. ~MemoryPack
  2281.  Src: MemoryXBsrc      Func: MemoryXB
  2282. struct MemoryPack {    /* MP
  2283.  unsigned  func;       /* 3
  2284.  unsigned  rstat;      /* ret:completion status
  2285.  unsigned long memory; /* ret:largest free OS memory block
  2286. See: OpenPack
  2287. ~OpenPack
  2288.  Src: OpenDXBsrc       Func: OpenDXB, OpenKXB
  2289. struct OpenPack {       /* OP
  2290.  unsigned  func;        /* 11=OpenDXB,21=OpenKXB
  2291.  unsigned  rstat;       /* ret:completion status
  2292.  unsigned  handle;      /* ret:OS handle of file opened
  2293.  char far *filenamePtr; /* far pointer to filenameZ to open
  2294.  unsigned  asMode;      /* DOS access-sharing mode(see OpenFileDOS)
  2295.  unsigned  xbLink;      /* if opening index this related data file
  2296. }; /* 14 */             /* (if opening data file xbHandle not used)
  2297. Note: you must supply xbLink on index file opens
  2298. See: RemotePack  OpenFileDOS
  2299. ~RemotePack
  2300.  Src: DriveRemoteXBsrc  Func: DriveRemoteXB, FileRemoteXB
  2301. struct RemotePack {  /* RP
  2302.  unsigned  func;     /* 86=DriveRemoteXB,87=FileRemoteXB
  2303.  unsigned  rstat;    /* ret:completion status
  2304.  unsigned  handle;   /* handle/drive depending on routine
  2305.  unsigned  isRemote; /* ret:0=local,1=remote
  2306.  unsigned  flags;    /* ret:dx register as returned by DOS
  2307.  unsigned  isShare;  /* ret:0=SHARE.EXE not loaded
  2308. }; /* 12 */
  2309. See: SetRetriesPack
  2310. ~SetRetriesPack
  2311.  Src: SetRetriesXBsrc  Func: SetRetriesXB
  2312. struct SetRetriesPack { /* SRP
  2313.  unsigned  func;        /* 88
  2314.  unsigned  rstat;       /* ret:completion status
  2315.  unsigned  mode;        /* 0=set DOS default else Pauses/Retries below
  2316.  unsigned  pause;       /* 0-65535 loop counter between retries
  2317.  unsigned  retries;     /* 0-65535 retries to access locked file
  2318. }; /* 10 */
  2319. The default values for Retries is 3 and Pause is 1.
  2320. The Pause value is used as a simple loop counter used to waste time. This loop
  2321. IS dependent on CPU power so values are not portable across different machines.
  2322. See: StatDataPack
  2323. ~StatDataPack
  2324.  Src: StatDXBsrc       Func: StatDXB
  2325. struct StatDataPack {   /* SDP
  2326.  unsigned  func;        /* 13
  2327.  unsigned  rstat;       /* ret:completion status
  2328.  unsigned  handle;      /* BULLET data file to get status on
  2329.  unsigned char fileType;/* ret:1=BULLET XB data file
  2330.  unsigned char dirty;   /* ret:0=not changed
  2331.  unsigned long recs;    /* ret:records in file
  2332.  unsigned  recLen;      /* ret:record length
  2333.  unsigned  fields;      /* ret:fields per record ()
  2334.  char      f1;          /* reserved (1=update DVmon)
  2335.  unsigned char LUyear;  /* ret:binary, year file last updated
  2336.  unsigned char LUmonth; /* ret:month--LUs are 0 if DBF newly created
  2337.  unsigned char LUday;   /* ret:day
  2338.  unsigned hereSeg;      /* ret:this file's control segment
  2339.  char filler[10];       /* reserved
  2340. }; /* 32 */
  2341. See: StatKeyPack
  2342. ~StatKeyPack
  2343.  Src: StatKXBsrc       Func: StatKXB
  2344. struct StatKeyPack {        /* SKP
  2345.  unsigned  func;            /* 23
  2346.  unsigned  rstat;           /* ret:completion status
  2347.  unsigned  handle;          /* BULLET key file to get status on
  2348.  unsigned  char fileType;   /* ret:0=BULLET XB key file
  2349.  unsigned  char dirty;      /* ret:0=not changed
  2350.  unsigned  long keys;       /* ret:keys in file
  2351.  unsigned  keyLen;          /* ret:key length
  2352.  unsigned  xbLink;          /* ret:related BULLET XB data handle
  2353.  unsigned  long xbRecNo;    /* ret:recno attached to current key
  2354.  unsigned  hereSeg;         /* ret:this file's control segment
  2355.  unsigned  codePageID;      /* ret:codepage of key file sort
  2356.  unsigned  countryCode;     /* ret:countrycode of key file sort
  2357.  unsigned  collateTableSize;/* ret:size of collate table, 0 or 256
  2358.  unsigned  keyFlags;        /* ret:bit 0=unique,1=char,4=int,
  2359.  char filler[2];            /*     5=long,E=NLS,F=signed
  2360. }; /* 32 */
  2361. See: StatHandlePack
  2362. ~StatHandlePack
  2363.  Src: StatHandleXBsrc  Func: StatHandleXB
  2364. struct StatHandlePack { /* SHP
  2365.  unsigned  func;        /* 6
  2366.  unsigned  rstat;       /* ret:completion status
  2367.  unsigned  handle;      /* file handle to get information on
  2368.  unsigned  ID;          /* ret:0=index,1=data,-1=not BULLET handle
  2369.  char far *filenamePtr; /* pointer to filename of handle
  2370. }; /* 12 */
  2371. See: XErrorPack
  2372. ~XErrorPack
  2373.  Src: GetExtErrorXBsrc Func: GetExtErrorXB
  2374. struct XerrorPack {  /* XEP
  2375.  unsigned  func;     /* 7
  2376.  unsigned  rstat;    /* ret:extended error
  2377.  unsigned  class;    /* ret:error class
  2378.  unsigned  action;   /* ret:suggested action
  2379.  unsigned  location; /* ret:error location
  2380. }; /* 10 */
  2381. See: AccessPack  Errors_DOS
  2382. ~Errors_BULLET    (200-209)
  2383. 200 key not found - The search key for Equal was not matched exactly.
  2384.     Next/Prev routines can be used to continue search from point of mismatch.
  2385. 201 key already exists - Attempted to add a key that already exists in the
  2386.     index file created to allow only unique keys.
  2387. 202 end of file - A Next routine is past the last key of the index file.
  2388. 203 top of file - A Prev routine is before the first key of the index file.
  2389. 204 key file empty - A key access was attempted with no keys in the index file.
  2390. 205 key type unknown - Generally indicates a corrupt index header (keyflags
  2391.     unknown at key insert).
  2392.     reserved,206-207
  2393. 208 no more nodes - The index file has reached full capacity (32MB). ReindexXB
  2394.     can often shrink an index file by 30 to 50%.
  2395. 209 key file corrupt - The index file is corrupt (write attempt to node 0).
  2396. See: Errors_BULLET_b
  2397. ~Errors_BULLET_b  (210-232)
  2398. 210 key file corrupt - The index file is corrupt (internal overflow).
  2399.     reserved,211-219
  2400. 220 incorrect DOS version - BULLET requires DOS 3.3 or later.
  2401. 221 invalid key length - The key is > 62 bytes (or 64 if unique specified).
  2402. 222 file not open - The specified handle is not an open BULLET file.
  2403.        
  2404.     reserved,223
  2405. 224 invalid record number - The specified record number is < 0, past the last
  2406.     record number in the .DBF, or is > 16,777,215.
  2407.     reserved,225-227
  2408. 228 invalid filetype - The specified handle is not the correct type for the
  2409.     operation (i.e., specifying a data file handle for a key file operation).
  2410.     reserved,229-232
  2411. See: Errors_BULLET_c
  2412. ~Errors_BULLET_c  (233-243)
  2413. 233 init not active - InitXB must be called before all others except MemoryXB.
  2414. 234 init already active - InitXB has already been called. Use ExitXB first to
  2415.     call InitXB more than once per process. (Make sure the xxP.Func <> 0.)
  2416. 235 too many indexes - BULLET can handle up to 32 index files per transaction
  2417.     record with the InsertXB and UpdateXB routines. Contact the author if you
  2418.     need to allow for more than 32 index files/transaction record.
  2419. 236 null record pointer passed to Bullet
  2420. 237 null key pointer passed to Bullet
  2421. 240 invalid key expression - The CreateKXB key expression could not be
  2422.     evaluated.
  2423.     reserved,238,239,241
  2424. 242 field not found - The fieldname was not found in the descriptor area.
  2425. 243 invalid field count - Too many fields were specified or the specified field
  2426.     number is past the last field.
  2427. See: Errors_BULLET_d
  2428. ~Errors_BULLET_d  (244-255)
  2429.     reserved,244-247 (248,249 see 250)
  2430. 250 invalid country info - The specifed country code or code page ID is not
  2431.     valid or not installed (according to DOS).  Also 248 and 249.
  2432. 251 invalid collate table size - The specified country code/code page ID uses
  2433.     a collate-sequence table > 256 bytes (2-byte characters as with Kanji).
  2434. 252 invalid keyflags - The specified keyflags are invalid.
  2435.     reserved,253-254
  2436. 255 evaluation mode shutdown - BULLET evaluation period has completed.
  2437.     You can reinstall to continue evaluation, though you may want to consider
  2438.     your motives for reinstalling since the original evaluation period has
  2439.     expired. This error occurs only after the evaluation period has expired.
  2440.     It is not recommended that you continue to use BULLET after the evaluation
  2441.     period. It is possible for no 255 error to be generated for quite some
  2442.     time since it occurs only under certain load conditions and then only when
  2443.     certain routine sequences are performed. The specified evaluation period of
  2444.     21 days should be adhered to.
  2445. See: Errors_DOS
  2446. ~Errors_DOS
  2447. -2 disk full or unexpected end of file (65534)
  2448. -1 bad filename (65535)                -3 Unexpected end of file (EOF)
  2449.  0 no error
  2450.  1 function not supported              19 disk write protected
  2451.  2 file not found                      20 unknown unit
  2452.  3 path not found                      21 drive not ready
  2453.  4 too many open files                 22 unknown command
  2454.  5 access denied (see Specs_Networks)  23 data error (CRC)
  2455.  6 handle invalid                      24 bad request structure length
  2456.  7 MCBs destroyed                      25 seek error
  2457.  8 not enough memory                   26 unknown medium type
  2458.  9 memory block address invalid        27 sector not found
  2459. 10 environment invalid                 28 printer out of paper
  2460. 11 format invalid                      29 write fault
  2461. 12 access code invalid                 30 read fault
  2462. 13 data invalid                        31 general failure
  2463.    reserved-0Eh                        32 sharing violation
  2464. 15 disk drive invalid                  33 lock violation
  2465. 16 cannot remove current directory     34 disk change invalid/wrong disk
  2466. 17 not same device                     35 FCB unavailable
  2467. 18 no more files                       36 sharing buffer overflow
  2468. See: Errors_DOS_b
  2469. ~Errors_DOS_b
  2470. 37 code page mismatched                58 incorrect response from network
  2471. 38 handle EOF                          59 unexpected network error
  2472. 39 handle disk full                    60 incompatible remote adapter
  2473.    reserved-28h                        61 print queue full
  2474.    reserved-29h                        62 no spool space
  2475.    reserved-2Ah                        63 not enough space to print file
  2476.    reserved-2Bh                        64 network name deleted
  2477.    reserved-2Ch                        65 network access denied
  2478.    reserved-2Dh                        66 network device type incorrect
  2479.    reserved-2Eh                        67 network name not found
  2480.    reserved-2Fh                        68 network name limit exceeded
  2481.    reserved-30h                        69 NETBIOS session limit exceeded
  2482.    reserved-31h                        70 sharing temporarily paused
  2483. 50 network request not supported       71 network request not accepted
  2484. 51 remote computer not listening       72 print/disk redirection paused
  2485. 52 duplicate name on network              reserved-49h
  2486. 53 network pathname not found             reserved-4Ah
  2487. 54 network busy                           reserved-4Bh
  2488. 55 network device no longer exists        reserved-4Ch
  2489. 56 NETBIOS command limit exceeded         reserved-4Dh
  2490. 57 network adapter hardware error         reserved-4Eh
  2491. See: Errors_DOS_c
  2492. ~Errors_DOS_c
  2493.    reserved-4Fh                  
  2494.  DOS Class Codes 
  2495. 80 file exists
  2496. 81 duplicate FCB                 1 out of resources       7 application error
  2497. 82 cannot make                   2 temporary situation    8 not found
  2498. 83 fail on INT24                 3 authorization          9 bad format
  2499. 84 out of structures             4 internal error        10 locked
  2500. 85 already assigned              5 hardware failure      11 media failure
  2501. 86 invalid password              6 system failure        12 already exists
  2502. 87 invalid parameter                                     13 unknown
  2503. 88 network write fault
  2504.    reserved-59h                    DOS Action Codes         DOS Locus Codes
  2505. 90 sys comp not loaded
  2506.                                  1 retry immediately      1 unknown
  2507.                                  2 delay and retry        2 block device
  2508.                                  3 reenter input          3 network
  2509.                                  4 abort ASAP             4 serial device
  2510.                                  5 abort immediately      5 memory
  2511.                                  6 ignore error
  2512.                                  7 user intervention
  2513. See: Errors_BULLET
  2514. ~InitXBsrc
  2515. Func: InitXB           Pack: InitPack           Func:   0/System
  2516. struct InitPack IP;
  2517. struct ExitPack EP;
  2518. IP.func = INITXB;       /* InitXB defined in BULLET.H
  2519. IP.JFTmode = 1;         /* expand JFT to 255 handles
  2520. rstat = BULLET(&IP);
  2521. if (rstat == 0) {
  2522.    EP.func = ATEXITXB;  /* register ExitXB with _atexit shutdown routine
  2523.    rstat = BULLET(&EP);
  2524. if (rstat != 0) /*error
  2525. Note: Due to space limitations all comments should be assumed to be terminated
  2526. on the same line (implicit */). Right.
  2527. See: ExitXBsrc
  2528. ~ExitXBsrc
  2529. Func: ExitXB           Pack: ExitPack           Func:   1/System
  2530. struct ExitPack EP;
  2531. EP.func = EXITXB      /* ExitXB defined in BULLET.H
  2532. rstat = BULLET(&EP)
  2533. The return value from ExitXB is currently always 0.
  2534. See: AtExitXBsrc
  2535. ~AtExitXBsrc
  2536. Func: AtExitXB         Pack: ExitPack           Func:   2/System
  2537. struct InitPack IP;
  2538. struct ExitPack EP;
  2539. IP.func = INITXB;       /* InitXB defined in BULLET.H
  2540. IP.JFTmode = 1;         /* expand JFT to 255 handles
  2541. rstat = BULLET(&IP);
  2542. if (rstat == 0) {
  2543.    EP.func = ATEXITXB;  /* register ExitXB with _atexit shutdown routine
  2544.    rstat = BULLET(&EP);
  2545. if (rstat != 0)  /* error
  2546. See: MemoryXBsrc
  2547. ~MemoryXBsrc
  2548. Func: MemoryXB         Pack: MemoryPack         Func:   3/System
  2549. struct MemoryPack MP;
  2550. MP.func = MEMORYXB;
  2551. rstat = BULLET(&MP);
  2552. /* MP.memory = amount of far heap available */
  2553. MP.memory does not reflect memory available through DOS in the UMB area. It's
  2554. possible that all memory requests can be satisfied by UMB RAM. Consult a DOS 5+
  2555. programmer reference for more information on this (see DOS INT21/58 for more).
  2556. See: BreakXBsrc
  2557. ~BreakXBsrc
  2558. Func: BreakXB          Pack: BreakPack          Func:   4/System
  2559. struct BreakPack BP;
  2560. BP.func = BREAKXB;    /* BreakXB defined in BULLET.H
  2561. BP.mode = 0;          /* disable Ctrl-C/Ctrl-BREAK (do nothing on those keys)
  2562. rstat = BULLET(&BP);  /* rstat=0 always
  2563. If BreakXB is called multiple times with the same BP.mode each time, only the
  2564. first is acted on. You can set BP.mode = 1 to restore the default handlers
  2565. (those installed originally) and then again set BP.Mode = 0 to disable them.
  2566. ExitXB calls this routine automatically as part of the BULLET shutdown to
  2567. restore the original default break handlers.
  2568. See: BackupFileXBsrc
  2569. ~BackupFileXBsrc
  2570. Func: BackupFileXB     Pack: CopyPack           Func:   5/System
  2571. struct AccessPack AP;
  2572. struct CopyPack CP;
  2573. CP.func = BACKUPFILEXB;         /* defined in BULLET.H
  2574. CP.handle = dataHandle;         /* handle of data file to backup
  2575. CP.filenamePtr = newFilename;   /* filename to save to
  2576. rstat = BULLET(&CP);
  2577. if (rstat == 0) {
  2578.    AP.func = PACKRECORDSXB;
  2579.    AP.handle = dataHandle;
  2580.    rstat = BULLET(&AP);
  2581. IF (rstat != 0) ... /* error
  2582. See: StatHandleXBsrc
  2583. ~StatHandleXBsrc
  2584. Func: StatHandleXB     Pack: StatHandlePack     Func:   6/System
  2585. struct StatHandlePack SHP;
  2586. struct StatKeyPack SKP;
  2587. struct StatDataPack SDP;
  2588. SHP.func = STATHANDLEXB;        /* defined in BULLET.H
  2589. SHP.handle = theHandleNumber;
  2590. rstat = BULLET(&SHP);
  2591. if (SHP.ID == 0) {     /* handle belongs to an index file (index file/key file)
  2592.    SKP.func = STATKXB; /* get key stats  -- see StatKXB/StatDXB for more
  2593.    SKP.handle = passedHandleNumber;     /* on the SKP structure
  2594.    rstat = BULLET(&SKP);
  2595. elseif (SHP.ID == 1) {   /*.DBF data file
  2596.    /* get DBF stats
  2597.    /* error not a BULLET file type
  2598. See: GetExtErrorXBsrc
  2599. ~GetExtErrorXBsrc
  2600. Func: GetExtErrorXB    Pack: XErrorPack         Func:   7/System
  2601. /* an error just occured in the range 1 to 199 as returned in one of the
  2602. /* pack.stat variables (current max DOS error is 90 (5Ah))
  2603. /* remember, transaction-based routines return a bad pack index in the return
  2604. /* rstat value, which you use to check the appropriate pack.Stat variable
  2605. struct XerrorPack XEP;
  2606. XEP.func = GETEXTERRORXB;       /* defined in BULLET.H
  2607. rstat = BULLET(&XEP);
  2608. if (rstat != 0) {
  2609.    /*             error=XEP.rstat
  2610.    /*       error class=XEP.class
  2611.    /* recommened action=XEP.action
  2612.    /*          location=XEP.location
  2613. See: DVmonCXBsrc  StatKXB
  2614. ~DVmonCXBsrc
  2615. Func: DVmonCXB         Pack: DVmonPack          Func:   9/DEBUG
  2616. /* at this point a data file and a key file have been opened
  2617. /* kf is that key file's DOS handle
  2618. struct DVmonPack DVP;
  2619. DV.func = DVMONCXB;     /* defined in BULLET.H
  2620. DV.mode = 1;            /* enable monitoring
  2621. DV.handle = kf;         /* monitor key file handle, kf (and its XBlink file)
  2622. DV.videoSeg = 0xB800+(4096/16);/* output to color screen, page 1 (pages 0 to ?)
  2623. rstat = BULLET(&DV);    /* rstat=0 always even if not DEBUG ENGINE
  2624. For two-monitor systems (with a color monitor as the main system) output should
  2625. be directed to 0xB000, the mono monitor's video memory.
  2626. DVmonCXB stands for Dual Video Monitor Control XB. This module is available
  2627. on the BBS in the BULLET conference files. It is not included in the
  2628. distribution.
  2629. See: CreateDXBsrc
  2630. ~CreateDXBsrc
  2631. Func: CreateDXB        Pack: CreateDataPack     Func:  10/Mid-level
  2632. struct CreateDataPack CDP;
  2633. struct FieldDescType fieldList[2]; /* fld descriptions for each of the fields..
  2634.                                    /* ...in the record (record has 2 fields)
  2635.                                    /* fieldList[] ** MUST ** be zero-filled
  2636. /* build FD first for each of the fields in the record
  2637. strcpy(fieldlist[0].fieldName, "STUDENT");  // note that unused bytes must
  2638. fieldlist[0].fieldType = 'C';               // be set to \0!
  2639. fieldlist[0].fieldLen = 20;
  2640. fieldlist[0].fieldDC = 0;
  2641. strcpy(fieldlist[1].fieldName, "SCORE");
  2642. fieldlist[1].fieldType = 'N';
  2643. fieldlist[1].fieldLen = 3;
  2644. fieldlist[1].fieldDC = 0;
  2645. /* (cont)
  2646.                      (for BINARY FieldType="B" see FieldDescType)
  2647. See: CreateDXBsrc_a                                                     -MORE-
  2648. ~CreateDXBsrc_a
  2649. /* build the CDP
  2650. CDP.func = CREATEDXB;           /* defined in BULLET.H
  2651. CDP.filenamePtr = filename;     /* filenameZ (Z=0-terminated str)
  2652. CDP.noFields = 2;               /* this example has 2 fields
  2653. CDP.fieldListPtr = fieldList    /* point to the first field decription...
  2654. CDP.fileID = 3;                 /* standard dBASE file ID
  2655. rstat = BULLET(&CDP);           /* create the DBF data file
  2656. if (rstat !=0) ... /* error
  2657. Normally this code would be written as a generalized FUNCTION. The CDP could be
  2658. a global allocation and the fieldlist would also.
  2659. BULLET can be customized very easily and with very little overhead. If you
  2660. don't like the default API, just develop your own using your own parameter
  2661. order, etc.
  2662. See: OpenDXBsrc  CreateDXBsrc
  2663. ~OpenDXBsrc
  2664. Func: OpenDXB          Pack: OpenPack           Func:  11/Mid-level
  2665. struct OpenPack OP;
  2666. OP.func = OPENDXB;                /* defined in BULLET.H
  2667. OP.filenamePtr = filename;        /* file to open (must already exist)
  2668. OP.asMode = ReadWrite | DenyNone; /* defined in BULLET.H
  2669. rstat = BULLET(&OP);
  2670. if (rstat !=0) ... /* error
  2671. The asMode (access/sharing mode) determines how the operating system controls
  2672. access to the file. See OpenFileDOS for the meanings of the various ASmodes.
  2673. See: CloseDXBsrc  OpenFileDOS
  2674. ~CloseDXBsrc
  2675. Func: CloseDXB         Pack: HandlePack         Func:  12/Mid-level
  2676. struct HandlePack HP;
  2677. HP.func = CLOSEDXB;           /* defined in BULLET.H
  2678. HP.handle = dataHandle;       /* handle of the file to close
  2679. rstat = BULLET(&HP);
  2680. if (rstat !=0) ... /* error
  2681. See: StatDXBsrc
  2682. ~StatDXBsrc
  2683. Func: StatDXB          Pack: StatDataPack       Func:  13/Mid-level
  2684. struct StatDataPack SDP;
  2685. SDP.func = STATDXB;        /* defined in BULLET.H
  2686. SDP.handle = dataHandle;   /* data handle to get stats on
  2687. rstat = BULLET(&SDP);      /* must be a data handle, use StatHandleXB if you...
  2688. if (rstat == 0) {          /* ...don't know the type of file a handle's for
  2689.    /* SDP.fileType is set to 1
  2690.    /* SDP.dirty is set to 1 if the file has changed (0=not changed)
  2691.    /* SDP.recs = number of records in the DBF file
  2692.    /* SDP.recLen = record length
  2693.    /* SDP.fields = number of fields in the record
  2694.    /* SDP.f1 is reserved
  2695.    /* SDP.LUyear = year file last updated, binary (year = ASC(SDP.LUyear))
  2696.    /* SDP.LUmonth = month, binary
  2697.    /* SDP.LUday = day, binary
  2698.    /* SDP.hereSeg is set to this handle's control segment (location in memory)
  2699. See: ReadDHXBsrc
  2700. ~ReadDHXBsrc
  2701. Func: ReadDHXB         Pack: HandlePack         Func:  14/Mid-level
  2702. struct HandlePack HP;
  2703. HP.func = READDHXB;          /* defined in BULLET.H
  2704. HP.handle = dataHandle;      /* handle of file whose header you want to reload
  2705. rstat = BULLET(&HP);
  2706. if (rstat != 0) ... /* error
  2707. This routine is automatically called by the network lock routines.
  2708. See: FlushDHXBsrc  LockDataXB
  2709. ~FlushDHXBsrc
  2710. Func: FlushDHXB        Pack: HandlePack         Func:  15/Mid-level
  2711. struct HandlePack HP;
  2712. HP.func = FLUSHDHXB;          /* defined in BULLET.H
  2713. HP.handle = dataHandle;       /* handle of file you want to flush
  2714. rstat = BULLET(&HP);
  2715. if (rstat != 0) ... /* error
  2716. Note that the physical write to disk is performed only if the file has changed
  2717. since the open or last flush.
  2718. This routine is automatically called by the network unlock routines.
  2719. See: CopyDHXBsrc  UnlockDataXB
  2720. ~CopyDHXBsrc
  2721. Func: CopyDHXBsrc      Pack: CopyPack           Func:  16/Mid-level
  2722. struct CopyPack CP;
  2723. CP.func = COPYDHXB;           /* defined in BULLET.H
  2724. CP.handle = dataHandle;       /* handle of file to copy from (the source)
  2725. CP.filenamePtr = filename;    /* far pointer to filenameZ for copy (dest)
  2726. rstat = BULLET(&CP);
  2727. if (rstat !=0) ... /* error
  2728. See: ZapDHXBsrc
  2729. ~ZapDHXBsrc
  2730. Func: ZapDHXB          Pack: HandlePack         Func:  17/Mid-level
  2731. struct HandlePack HP;
  2732. HP.func = ZAPDHXB;            /* defined in BULLET.H
  2733. HP.handle = dataHandle;       /* handle of file you want !ZAP!
  2734. rstat = BULLET(&HP);
  2735. if (rstat !=0)... /* error
  2736. Note that this removes ALL data records from the data file.
  2737. See: CreateKXBsrc
  2738. ~CreateKXBsrc
  2739. Func: CreateKXB        Pack: CreateKeyPack      Func:  20/Mid-level
  2740. /* This code assumes that the datafile was created as in CreateDXBsrc, and that
  2741. /* the datafile was opened as in OpenDXBsrc.
  2742. strcpy(keyEpression,"SUBSTR(STUDENT,1,5)"); /* a non-unique, character key
  2743. struct CreateKeyPack CKP;
  2744. CKP.func = CREATEKXB;           /* defined in BULLET.H
  2745. CKP.filenamePtr = filename;     /* far pointer to filenameZ
  2746. CKP.keyExpPtr = keyExpression;  /* far pointer to key expressionZ
  2747. CKP.xbLink = datahandle;        /* the datafile handle returned from OpenDXB
  2748. CKP.keyFlags = cCHAR;           /* -KEYFLAGS- are defined in BULLET.H
  2749. CKP.codePageID = -1;            /* use DOS default code page ID
  2750. CKP.countryCode = -1;           /* use DOS default country code
  2751. CKP.collatePtrOff = 0;          /* no user-supplied collate table...
  2752. CKP.collatePtrSeg = 0;          /* ...
  2753. rstat = BULLET(&CKP);
  2754. IF (rstat !=0) ... /* error
  2755. Normally this code would be written as a generalized FUNCTION.
  2756. See: OpenKXBsrc  CreateKXBsrc
  2757. ~OpenKXBsrc
  2758. Func: OpenKXB          Pack: OpenPack           Func:  21/Mid-level
  2759. struct OpenPack OP;
  2760. OP.func = OPENKXB;               /* defined in BULLET.H
  2761. OP.filenamePtr = filename;       /* point to filenameZ (Z=0-terminated str)
  2762. OP.asMode = ReadWrite | DenyNone;/* defined in BULLET.H
  2763. OP.xbLink = dataFileHandle;      /* OpenKXB needs to know the data file handle
  2764. rstat = BULLET(&OP);
  2765. if (rstat !=0) ... /* error
  2766. The asMode (access/sharing mode) determines how the operating system controls
  2767. access to the file. See OpenFileDOS for the meanings of the various ASmodes.
  2768. Before you can open an index file you must first open its associated data file.
  2769. See: CloseKXBsrc  OpenFileDOS
  2770. ~CloseKXBsrc
  2771. Func: CloseKXB         Pack: HandlePack         Func:  22/Mid-level
  2772. struct HandlePack HP;
  2773. HP.func = CLOSEDXB;           /* defined in BULLET.H
  2774. HP.handle = indexhandle;      /* handle of the file to close
  2775. rstat = BULLET(&HP);
  2776. if (rstat !=0) ... /* error
  2777. See: StatKXBsrc
  2778. ~StatKXBsrc
  2779. Func: StatKXB          Pack: StatKeyPack        Func:  23/Mid-level
  2780. struct StatKeyPack SKP;
  2781. SKP.func = STATKXB;       /* defined in BULLET.H
  2782. SKP.handle = indexHandle; /* handle to get stats on
  2783. rstat = BULLET(&SKP);     /* must be index handle, use StatHandleXB if you...
  2784. if (rstat == 0) {         /* ...don't know the type of file a handle's for
  2785.   /* SKP.filetype is set to 0
  2786.   /* SKP.dirty is set to 1 if the file has changed (0=not changed)
  2787.   /* SKP.keys = number of key in the index file (index file=key file)
  2788.   /* SKP.keyLen = physical key length (1-64 bytes)
  2789.   /* SKP.xbLink = datafile handle that this index file is associated with
  2790.   /* SKP.xbRecNo is set to record number associated with last accessed key
  2791.   /* SKP.hereSeg is set to this handle's control segment (location in memory)
  2792.   /* SKP.codePageID returns this index file's permanent code page ID
  2793.   /* SKP.countryCode returns this index file's permanent country code
  2794.   /* SKP.collateTableSize = 0 (no collate table present) or 256 (table present)
  2795.   /* SKP.keyFlags= key flags specifed at CreateKXB (except NLS flag may be set)
  2796. else                                               (NLS flag is bit 14, 0x4000)
  2797.   /* error
  2798. See: ReadKHXBsrc
  2799. ~ReadKHXBsrc
  2800. Func: ReadKHXB         Pack: HandlePack         Func:  24/Mid-level
  2801. struct HandlePack HP;
  2802. HP.func = READKHXB;           /* defined in BULLET.H
  2803. HP.handle = indexHandle;      /* handle of file whose header you want to reload
  2804. rstat = BULLET(&HP);
  2805. if (rstat !=0) ... /* error
  2806. This routine is automatically called by the network lock routines.
  2807. See: FlushKHXBsrc  LockKeyXB
  2808. ~FlushKHXBsrc
  2809. Func: FlushKHXB        Pack: HandlePack         Func:  25/Mid-level
  2810. struct HandlePack HP;
  2811. HP.func = FLUSHKHXB;          /* defined in BULLET.H
  2812. HP.handle = indexHandle;      /* handle of file you want to flush
  2813. rstat = BULLET(&HP);
  2814. if (rstat !=0) ... /* error
  2815. Note that the physical write to disk is performed only if the file has changed
  2816. since the open or last flush.
  2817. This routine is automatically called by the network unlock routines.
  2818. See: CopyKHXBsrc  UnlockKeyXB
  2819. ~CopyKHXBsrc
  2820. Func: CopyKHXBsrc      Pack: CopyPack           Func:  26/Mid-level
  2821. struct CopyPack CP;
  2822. CP.func = COPYKHXB;           /* defined in BULLET.H
  2823. CP.handle = indexHandle;      /* handle of file to copy from (the source)
  2824. CP.filenamePtr = filename;    /* far pointer to filenameZ for copy
  2825. rstat = BULLET(&CP);
  2826. if (rstat !=0) ... /* error
  2827. See: ZapKHXBsrc
  2828. ~ZapKHXBsrc
  2829. Func: ZapKHXB          Pack: HandlePack         Func:  27/Mid-level
  2830. struct HandlePack HP;
  2831. HP.func = ZAPKHXB;              /* defined in BULLET.H
  2832. HP.handle = indexHandle;        /* handle of file you want !ZAP!
  2833. rstat = BULLET(&HP);
  2834. if (rstat !=0) ... /* error
  2835. Note that this removes ALL keys from the index file.
  2836. See: GetDescriptorXBsrc
  2837. ~GetDescriptorXBsrc
  2838. Func: GetDescriptorXB  Pack: DescriptorPack     Func:  30/Mid-level
  2839. struct DesciptorPack DP;
  2840. DP.func = GETDESCRIPTORXB;            /* defined in BULLET.H
  2841. DP.handle = dataHandle;               /* handle of file
  2842. if (fieldnumber > 0) {
  2843.    DP.fieldnumber = fieldnumber;      /* field number to get info on
  2844. else {                                /* or, if 0, then
  2845.    DP.fieldNumber = 0;
  2846.    strcpy(DP.FD.fieldName,fieldName); /* fieldname to get info on
  2847. rstat = BULLET(&DP);
  2848. if rstat == 0 {
  2849.    /* DP.FD.fieldName is set to field name
  2850.    /* DP.FD.fieldType is set to field type
  2851.    /* DP.FD.fieldLen is set to field length
  2852.    /* DP.FD.fieldDC is set to field DC
  2853.    /* error
  2854. See: GetRecordXBsrc
  2855. ~GetRecordXBsrc
  2856. Func: GetRecordXB      Pack: AccessPack         Func:  31/Mid-level
  2857. struct RecType {            /* simple DBF record layout
  2858.         char  tag;      <
  2859.         char  code[5];      
  2860. THE FIRST BYTE OF YOUR RECORD TYPES MUST BE TAG! 
  2861.         char  bday[9];      
  2862. }; /* 15 */
  2863. struct RecType recBuff;     /* record has 2 fields, code/C/4.0, bday/D/8.0
  2864. struct AccessPack AP;
  2865. AP.func = GETRECORDXB;      /* defined in BULLET.H
  2866. AP.handle = dataHandle;     /* handle to get record from
  2867. AP.recNo = recNoToGet;      /* record number to get
  2868. AP.recPtr = recBuff;        /* read record from disk into recbuff
  2869. rstat = BULLET(&AP);
  2870. if (rstat == 0) {
  2871.    /* recbuff.code and .bday set to contents of record number (recnotoget)
  2872.    /* error
  2873. /* Be aware of side effects of using C strings (the \0) within a DBF record */
  2874. See: AddRecordXBsrc
  2875. ~AddRecordXBsrc
  2876. Func: AddRecordXB      Pack: AccessPack         Func:  32/Mid-level
  2877. struct RecType {            /* simple DBF record layout
  2878.         char  tag;      <
  2879.         char  code[5];      
  2880. THE FIRST BYTE OF YOUR RECORD TYPES MUST BE TAG! 
  2881.         char  bday[8];      
  2882. }; /* 14 */
  2883. struct RecType recBuff;     /* record has 2 fields, code/C/4.0, bday/D/8.0
  2884. struct AccessPack AP;
  2885. /* be sure to init the tag field to a space (ASCII 32)
  2886. recBuff.tag = ' ';
  2887. strcpy(recBuff.code,"1234");     /* actually uses 5 bytes with \0 */
  2888. strncpy(recBuff.bday,"19331122",8); /* and 8 here  (no \0 on dBIII DATE */
  2889. AP.func = ADDRECORDXB;      /* defined in BULLET.H
  2890. AP.handle = dataHandle;     /* handle to put record to
  2891. AP.recPtr = recBuff;        /* write recBuff to disk
  2892. rstat = BULLET(&AP);
  2893. if (rstat == 0) {
  2894.    /* AP.recNo set to record number to used by just written record
  2895. See: UpdateRecordXBsrc
  2896. ~UpdateRecordXBsrc
  2897. Func: UpdateRecordXB   Pack: AccessPack         Func:  33/Mid-level
  2898. /* see GetRecordXBsrc for this source example's preliminary code
  2899. AP.func = GETRECORDXB;          /* first get the record to update
  2900. AP.handle = dataHandle;         /* 
  2901. AP.recNo = recNoToGet;          /* 
  2902.  Do NOT use UpdateRecordXB to change   
  2903. AP.recPtr = recBuff;            /* 
  2904.  any field(s) used in a key expression.
  2905. rstat = BULLET(&AP);            /* 
  2906.  Instead use UpdateXB.                 
  2907. if (rstat==0) {                 /* 
  2908.    strncpy(recBuff.dbay,"19591122",8); // change only non-key portions of rec
  2909.    AP.func = UPDATERECORDXB;        /* defined in BULLET.H
  2910.    rstat = BULLET(&AP)              /* other AP. values are already set by Get
  2911. if (rstat !=0) ... /* error
  2912. See: DeleteRecordXBsrc  UpdateXB
  2913. ~DeleteRecordXBsrc
  2914. Func: DeleteRecordXB   Pack: AccessPack         Func:  34/Mid-level
  2915. struct AccessPack AP;
  2916. AP.func = DELETERECORDXB;     /* defined in BULLET.H
  2917. AP.handle = dataHandle;       /* handle of record to delete
  2918. AP.recNo = recNoToDelete;     /* to determine which record number any record
  2919. rstat = BULLET(&AP);          /* is, use one of the keyed access routines
  2920. if (rstat !=0) ... /* error
  2921. See: UndeleteRecordsrc (XB)
  2922. ~UndeleteRecordsrc (XB)
  2923. Func: UndeleteRecordXB Pack: AccessPack         Func:  35/Mid-level
  2924. struct AccessPack AP;
  2925. AP.func = UNDELETERECORDXB;   /* defined in BULLET.H
  2926. AP.handle = dataHandle;       /* handle of record to undelete
  2927. AP.recNo = recNoToUndelete;   /* to determine which record number any record
  2928. rstat = BULLET(&AP);          /* is, use one of the keyed access routines
  2929. if (rstat !=0) ... /* error
  2930. See: PackRecordsXBsrc
  2931. ~PackRecordsXBsrc
  2932. Func: PackRecordsXB    Pack: AccessPack         Func:  36/Mid-level
  2933. struct AccessPack AP;
  2934. AP.func = PACKRECORDSXB;      /* defined in BULLET.H
  2935. AP.handle = dataHandle;       /* handle of data file to pack
  2936. rstat = BULLET(&AP);
  2937. if (rstat !=0) ... /* error
  2938. See: FirstKeyXBsrc
  2939. ~FirstKeyXBsrc
  2940. Func: FirstKeyXB       Pack: AccessPack         Func:  40/Mid-level
  2941. struct AccessPack AP;
  2942. AP.func = FIRSTKEYXB;         /* defined in BULLET.H
  2943. AP.handle = indexHandle;      /* handle to index file to access key from
  2944. AP.keyPtr = keyBuffer;        /* far pointer to key buffer
  2945. rstat = BULLET(&AP);
  2946. if (rstat==0) {
  2947.    /* keybuff is filled in with the key (for as many bytes as the key length)
  2948.    /* When using the key returned, be aware that if UNIQUE was NOT specified
  2949.    /* then the enumerator word is attached to the end of the key (the right
  2950.    /* two bytes).
  2951.    /* Also, AP.recNo is set to the record number of the first key in the index.
  2952.    /* error
  2953. See: EqualKeyXBsrc
  2954. ~EqualKeyXBsrc
  2955. Func: EqualKeyXB       Pack: AccessPack         Func:  41/Mid-level
  2956. struct AccessPack AP;
  2957. AP.func = EQUALKEYXB;         /* defined in BULLET.H
  2958. AP.handle = indexHandle;      /* handle to index file to find key from
  2959. AP.keyPtr = keyBuffer;        /* far pointer to key buffer (include enumerator
  2960. rstat = BULLET(&AP);          /* if non-UNQIUE key) (double NULL good start)
  2961. if (rstat==0) {
  2962.    /* the key matched exactly (including enumerator, if present)
  2963.    /* keybuff is NOT ALTERED
  2964.    /* AP.recNo is set to the record number of that key
  2965.    if (rstat == 200) {
  2966.       AP.func = NEXTKEYXB     /* if not found, get following key and check the
  2967.       rstat = BULLET(&AP)     /* key proper (key less the enumerator bytes)
  2968.       if (rstat==0) {         /* (i.e., it may be proper key but enumerator=1)
  2969.          /* see NextKeyXBsrc for continuation
  2970. See: NextKeyXBsrc
  2971. ~NextKeyXBsrc
  2972. Func: NextKeyXB        Pack: AccessPack         Func:  42/Mid-level
  2973. /* see EqualKeyXBsrc for preliminary code
  2974. AP.func = NEXTKEYXB;           /* defined in BULLET.H
  2975. rstat = BULLET(&AP);           /* KEYLEN assumed to equal actual key length...
  2976. if (rstat==0) {                /* ...as returned by StatKXB
  2977.    if (IndexFileIsNotUnique) {
  2978.        if (KeyProperMatchesKeyToFind) {
  2979.           /* found a match to the key proper
  2980. This code example follows up on the EqualKeyXBsrc example. See EqualKeyXB for
  2981. more information on finding partial keys.
  2982. See: PrevKeyXBsrc  EqualKeyXBsrc
  2983. ~PrevKeyXBsrc
  2984. Func: PrevKeyXB        Pack: AccessPack         Func:  43/Mid-level
  2985. struct accesspack AP;
  2986. /* assume code has already executed to locate a key--this code then gets the
  2987. /* key before that one
  2988. AP.func = PREVKEYXB;          /* defined in BULLET.H
  2989. AP.handle = indexHandle;      /* handle to index file to access key from
  2990. AP.keyPtr = keyBuff;          /* far pointer to key buffer
  2991. rstat = BULLET(&AP);
  2992. if (rstat==0) {
  2993.    /* keybuff is filled in with the key (for as many bytes as the key length).
  2994.    /* Also, AP.recno is set to the record number of the key.
  2995.    /* error
  2996. See: LastKeyXBsrc
  2997. ~LastKeyXBsrc
  2998. Func: LastKeyXB        Pack: AccessPack         Func:  44/Mid-level
  2999. struct accesspack AP;
  3000. AP.func = LASTKEYXB;          /* defined in BULLET.H
  3001. AP.handle = indexHandle;      /* handle to index file to access key from
  3002. AP.keyPtr = keyBuff;          /* far pointer to key buffer
  3003. rstat = BULLET(&AP);
  3004. if (rstat==0) {
  3005.    /* keybuff is filled in with the key (for as many bytes as the key length).
  3006.    /* Also, AP.recNo is set to the record number of the last key.
  3007.    /* error
  3008. See: StoreKeyXBsrc
  3009. ~StoreKeyXBsrc
  3010. Func: StoreKeyXB       Pack: AccessPack         Func:  45/Mid-level
  3011. struct AccessPack AP;
  3012. /* Assume record has been added to data file (AddRecordXB, returning recno2use)
  3013. /* and key has been built (BuildKeyXB returning keytoadd[]).
  3014.               
  3015. AP.func = STOREKEYXB;         /* defined in BULLET.H
  3016. AP.handle = indexHandle;      /* handle to index file to insert key into
  3017. AP.recNo = recNoToUse;        /* associate this record number with key
  3018. AP.keyPtr = keyToAdd;         /* far pointer to key buffer
  3019. rstat = BULLET(&AP);
  3020. if (rstat==0) {
  3021.    /* key added
  3022.    if (rstat==201) {
  3023.       /* key already exists, you need to construct a unique enumerator--
  3024.       /* provided file wasn't created for UNIQUE keys...INSTEAD USE InsertXB!
  3025.    else
  3026.       /* other error
  3027. See: DeleteKeyXBsrc  InsertXB
  3028. ~DeleteKeyXBsrc
  3029. Func: DeleteKeyXB      Pack: AccessPack         Func:  46/Mid-level
  3030. struct AccessPack AP;
  3031. AP.func = DELETEKEYXB;         /* defined in BULLET.H
  3032. AP.handle = indexHandle;       /* handle to index file of key to delete
  3033. AP.keyPtr = keyBuffer;         /* far pointer to key buffer (incl enum)
  3034.                                /* (this key is searched for exactly)
  3035. rstat = BULLET(&AP);           /* if exact match found the key is deleted!
  3036. if (rstat==0) {
  3037.    /* key deleted permanently
  3038. if (rstat==200) {
  3039.    /* key as stated was not in the index file--if the index is not UNQIUE then
  3040.    /* you must supply the exact enumerator along with the key proper to delete
  3041.    /* --you can use the CurrentKeyXB routine to obtain the exact current key
  3042.    /* other error
  3043. See: BuildKeyXBsrc
  3044. ~BuildKeyXBsrc
  3045. Func: BuildKeyXB       Pack: AccessPack         Func:  47/Mid-level
  3046. struct AccessPack AP;
  3047. /* Assume record has been built and is ready to be added to the data file. The
  3048. /* record is in the variable recbuff.
  3049. AP.func = BUILDKEYXB;        /* defined in BULLET.H
  3050. AP.handle = indexHandle;     /* handle to index file key is to be built for
  3051. AP.recPtr = recBuff;         /* far pointer to data record buffer
  3052. AP.keyPtr = keyBuff;         /* far pointer to key buffer
  3053. rstat = BULLET(&AP)
  3054. if (rstat==0) {
  3055.    /* key built okay so can do a AddRecordXB followed by a StoreKeyXB
  3056.    /* but, again, InsertXB takes care of all this detail and then some--use it
  3057.    /* error
  3058. See: CurrentKeyXBsrc
  3059. ~CurrentKeyXBsrc
  3060. Func: CurrentKeyXB     Pack: AccessPack         Func:  48/Mid-level
  3061. struct accesspack AP;
  3062. AP.func = CURRENTKEYXB;         /* defined in BULLET.H
  3063. AP.handle = indexHandle;        /* handle to index file
  3064. AP.keyPtr = keyBuff;            /* far pointer to key buffer
  3065. rstat = BULLET(&AP);
  3066. if (rstat==0) {
  3067.    /* keybuff set to current key (valid only for KeyLen bytes)
  3068.    /* Also, AP.recno is set to the record number of the key.
  3069.    /* error
  3070. See: GetFirstXBsrc
  3071. ~GetFirstXBsrc
  3072. Func: GetFirstXB       Pack: AccessPack         Func:  60/High-level
  3073. struct AccessPack AP;
  3074. AP.func = GETFIRSTXB;           /* defined in BULLET.H
  3075. AP.handle = indexHandle;        /* handle to index file to access key from
  3076. AP.recPtr = recBuff;            /* far pointer to record buffer
  3077. AP.keyPtr = keyBuff;            /* far pointer to key buffer
  3078. rstat = BULLET(&AP);
  3079. if (rstat==0) {
  3080.    /* keyBuff is filled in with the key (for as many bytes as the key length)
  3081.    /* recBuff is filled in with the data record
  3082.    /* AP.recNo is set to the record number of the first key in the index.
  3083.    /* error
  3084. See: GetEqualXBsrc
  3085. ~GetEqualXBsrc
  3086. Func: GetEqualXB       Pack: AccessPack         Func:  61/High-level
  3087. struct accesspack AP;
  3088. AP.func = GETEQUALXB;           /* defined in BULLET.H
  3089. AP.handle = indexHandle;        /* handle to index file to access key from
  3090. AP.recPtr = recBuff;            /* far pointer to record buffer
  3091. AP.keyPtr = keyBuff;            /* far pointer to key buffer
  3092. rstat = BULLET(&AP);
  3093. if (rstat==0) {
  3094.    /* recBuff and AP.recNo filled as expected (keyBuff remains the same)
  3095.    if (rstat==200) {
  3096.       AP.func = GETNEXTXB;  /* if not found, can get following key--the next
  3097.       rstat = BULLET(&AP);  /* key would logically follow the key not found
  3098.    else
  3099.       /* error
  3100. See: GetNextXBsrc
  3101. ~GetNextXBsrc
  3102. Func: GetNextXB        Pack: AccessPack         Func:  62/High-level
  3103. struct AccessPack AP;
  3104. AP.func = GETNEXTXB;            /* defined in BULLET.H
  3105. AP.handle = indexHandle;        /* handle to index file to access key from
  3106. AP.recPtr = recBuff;            /* far pointer to record buffer
  3107. AP.keyPtr = keyBuff;            /* far pointer to key buffer
  3108. rstat = BULLET(&AP);
  3109. if (rstat==0) {
  3110.    /* keyBuff is filled in with the next key (as many bytes as the key length)
  3111.    /* recBuff is filled in with the data record
  3112.    /* AP.recNo is set to the record number of the next key in the index
  3113.    /* This key is made the current key so GETNEXTXB again gets next, and so on
  3114.    /* error
  3115. See: GetPrevXBsrc
  3116. ~GetPrevXBsrc
  3117. Func: GetPrevXB        Pack: AccessPack         Func:  63/High-level
  3118. struct accesspack AP;
  3119. AP.func = GETPREVXB;            /* defined in BULLET.H
  3120. AP.handle = indexhandle;        /* handle to index file to access key from
  3121. AP.recPtr = recBuff;            /* far pointer to record buffer
  3122. AP.keyPtr = keyBuff;            /* far pointer to key buffer
  3123. rstat = BULLET(&AP);
  3124. if (rstat==0) {
  3125.    /* keyBuff is filled in with the prev key (as many bytes as the key length)
  3126.    /* recBuff is filled in with the data record
  3127.    /* AP.recNo is set to the record number of the prev key in the index
  3128.    /* This key is made the current key so GETPREVXB again gets prev, and so on
  3129.    /* error
  3130. See: GetLastXBsrc
  3131. ~GetLastXBsrc
  3132. Func: GetLastXB        Pack: AccessPack         Func:  64/High-level
  3133. struct AccessPack AP;
  3134. AP.func = GETLASTXB;            /* defined in BULLET.H
  3135. AP.handle = indexHandle;        /* handle to index file to access key from
  3136. AP.recPtr = recBuff;            /* far pointer to record buffer
  3137. AP.keyPtr = keyBuff;            /* far pointer to key buffer
  3138. rstat = BULLET(&AP);
  3139. if (rstat==0) {
  3140.    /* keyBuff is filled in with the key (for as many bytes as the key length)
  3141.    /* recBuff is filled in with the data record
  3142.    /* AP.recNo is set to the record number of the last key in the index.
  3143.    /* error
  3144. See: InsertXBsrc
  3145. ~InsertXBsrc
  3146. Func: InsertXB         Pack: AccessPack         Func:  65/High-level
  3147. struct AccessPack AP[3];   /* array of 3 access packs, 1 for each index file
  3148.                            /* keyBuff and recBuff previously defined
  3149. for (i=0,i<3,i++) {        /* 3=number of related indexes to maintain
  3150.    AP[i].func = INSERTXB;
  3151.    AP[i].handle = indexHandle[i]; /* each index file's handle
  3152.    AP[i].recPtr = recBuff;
  3153.    AP[i].keyPtr = keyBuff;
  3154.    AP[i].nextPtr = &AP[i+1];    /* point to NEXT access pack
  3155. AP[2].nextPtr = NULL;           /* reset last access pack to end-link value
  3156. rstat = BULLET(&AP);
  3157. if (rstat==0) {                 /* if rstat=0 must still check AP[0].stat
  3158.    if (AP[0].stat != 0) {       /* error when adding data record
  3159.       /* error }
  3160.    trueError = AP[rstat-1].stat; /* returned rstat is array index of bad pack
  3161.                                  /* -1 since C packs are 0 based.
  3162. See: UpdateXBsrc
  3163. ~UpdateXBsrc
  3164. Func: UpdateXB         Pack: AccessPack         Func:  66/High-level
  3165. struct AccessPack AP[3];   /* array of 3 access packs, 1 for each index file
  3166.                            /* keyBuff and recBuff previously defined
  3167. for (i=0,i<3,i++) {        /* 3=number of related indexes to maintain
  3168.    AP[i].func = UPDATEXB;
  3169.    AP[i].handle = indexHandle[i]; /* each index file's handle
  3170.    AP[i].recNo = recordNumberToUpdate; /* the record number to update
  3171.    AP[i].recPtr = recBuff;
  3172.    AP[i].keyPtr = keyBuff;
  3173.    AP[i].nextPtr = &AP[i+1];    /* point to NEXT access pack
  3174. AP[2].nextPtr = NULL;           /* reset last access pack to end-link value
  3175. rstat = BULLET(&AP);
  3176. if (rstat==0) {                 /* if rstat=0 must still check AP[0].stat
  3177.    if (AP[0].stat != 0) {       /* error when adding data record
  3178.       /* error }
  3179.    trueerror = AP[rstat-1].stat; /* returned rstat is array index of bad pack
  3180.                                  /* -1 since C packs are 0 based.
  3181. See: ReindexXBsrc
  3182. ~ReindexXBsrc
  3183. Func: ReindexXB        Pack: AccessPack         Func:  67/High-level
  3184. struct AccessPack AP[3];   /* array of 3 access packs, 1 for each index file
  3185.                            /* keyBuff and recBuff previously defined
  3186. for (i=0,i<3,i++) {        /* 3=number of related indexes to maintain
  3187.    AP[i].func = REINDEXB;
  3188.    AP[i].handle = indexHandle[i]; /* each index file's handle
  3189.    AP[i].nextPtr = &AP[i+1];    /* point to NEXT access pack
  3190. AP[2].nextPtr = NULL;           /* reset last access pack to end-link value
  3191. rstat = BULLET(&AP);
  3192. if (rstat !=0) {
  3193.    trueerror = AP[rstat-1].stat;  /* returned rstat is array index of bad pack
  3194.                                   /* -1 since C packs are 0 based.
  3195. See: LockXBsrc
  3196. ~LockXBsrc
  3197. Func: LockXB           Pack: AccessPack         Func:  80/Network
  3198. struct AccessPack AP[3];   /* array of 3 access packs, 1 for each index file
  3199. for (i=0,i<3,i++) {        /* 3=number of related indexes to maintain
  3200.    AP[i].func = LOCKXB;
  3201.    AP[i].handle = indexHandle[i]; /* each index file's handle
  3202.    AP[i].nextPtr = &AP[i+1];    /* point to NEXT access pack
  3203. AP[2].nextPtr = NULL;           /* reset last access pack to end-link value
  3204. rstat = BULLET(&AP);
  3205. if (rstat > 3) {                /* if rstat > 3 (> number of packs) then the...
  3206.    trueError = AP[0].stat;      /* ...lock failed on the data file
  3207. else                            /* and the error code is in the FIRST pack
  3208.    if (rstat !=0) {
  3209.       trueError = AP[rstat-1].stat  /*...lock failed on index file # rstat
  3210.                                     /* -1 since C packs are 0 based.
  3211. The Lock routines use a different method to identify the bad pack when the   
  3212. failure was caused by the data file. See above.                              
  3213. See: UnlockXBsrc
  3214. ~UnlockXBsrc
  3215. Func: UnlockXB         Pack: AccessPack         Func:  81/Network
  3216. struct AccessPack AP[3];   /* array of 3 access packs, 1 for each index file
  3217. for (i=0,i<3,i++) {        /* 3=number of related indexes to maintain
  3218.    AP[i].func = UNLOCKXB;
  3219.    AP[i].handle = indexHandle[i]; /* each index file's handle
  3220.    AP[i].nextPtr = &AP[i+1];    /* point to NEXT access pack
  3221. AP[2].nextPtr = NULL;           /* reset last access pack to end-link value
  3222. rstat = BULLET(&AP);
  3223. if (rstat > 3) {                /* if rstat > 3 (> number of packs) then the...
  3224.    trueError = AP[0].stat;      /* ...unlock failed on the data file
  3225. else                            /* and the error code is in the FIRST pack
  3226.    if (rstat !=0) {
  3227.       trueError = AP[rstat-1].stat  /*...unlock failed on index file # rstat
  3228.                                     /* -1 since C packs are 0 based.
  3229. The Lock routines use a different method to identify the bad pack when the   
  3230. failure was caused by the data file. See above.                              
  3231. See: LockKeyXBsrc
  3232. ~LockKeyXBsrc
  3233. Func: LockKeyXB        Pack: AccessPack         Func:  82/Network
  3234. struct AccessPack AP[3];   /* array of 3 access packs, 1 for each index file
  3235. for (i=0,i<3,i++) {        /* 3=number of related indexes to maintain
  3236.    AP[i].func = LOCKKEYXB;
  3237.    AP[i].handle = indexHandle[i]; /* each index file's handle
  3238.    AP[i].nextPtr = &AP[i+1];    /* point to NEXT access pack
  3239. AP[2].nextPtr = NULL;           /* reset last access pack to end-link value
  3240. rstat = BULLET(&AP);
  3241. if (rstat !=0) {
  3242.    trueError = AP[rstat-1].stat  /*...lock failed on index file # rstat
  3243.                                  /* -1 since C packs are 0 based.
  3244.                          /*--if rstat > packs (3) then failed on last internal
  3245.                          /*--ReadKHXB...This is EXTREMELY unlikely
  3246. See: UnlockKeyXBsrc
  3247. ~UnlockKeyXBsrc
  3248. Func: UnlockKeyXB      Pack: AccessPack         Func:  83/Network
  3249. struct AccessPack AP[3];   /* array of 3 access packs, 1 for each index file
  3250. for (i=0,i<3,i++) {        /* 3=number of related indexes to maintain
  3251.    AP[i].func = UNLOCKKEYXB;
  3252.    AP[i].handle = indexHandle[i]; /* each index file's handle
  3253.    AP[i].nextPtr = &AP[i+1];    /* point to NEXT access pack
  3254. AP[2].nextPtr = NULL:           /* reset last access pack to end-link value
  3255. rstat = BULLET(&AP);
  3256. if (rstat !=0) {
  3257.    trueError = AP[rstat-1].stat  /*...lock failed on index file # rstat
  3258.                                  /* -1 since C packs are 0 based.
  3259. See: LockDataXBsrc
  3260. ~LockDataXBsrc
  3261. Func: LockDataXB       Pack: AccessPack         Func:  84/Network
  3262. struct AccessPack AP;
  3263. AP.func = LOCKDATAXB;         /* defined in BULLET.H
  3264. AP.handle = dataHandle;       /* handle of data file to lock
  3265. AP.recNo = 0L;                /* =0 to lock all or, set to actual record number
  3266. rstat = BULLET(&AP);          /*    to lock as in AP.recNo = lockThisRec
  3267. if (rstat !=0) ... /* error
  3268. See: UnlockDataXBsrc
  3269. ~UnlockDataXBsrc
  3270. Func: UnlockDataXB     Pack: AccessPack         Func:  85/Network
  3271. struct AccessPack AP;
  3272. AP.func = UNLOCKDATAXB;       /* defined in BULLET.H
  3273. AP.handle = dataHandle;       /* handle of data file to unlock
  3274. AP.recNo = 0L;                /* =0 to unlock all or, set to actual record num
  3275. rstat = BULLET(&AP);          /*    to unlock as in AP.recNo = lockThisRec
  3276. if (rstat !=0) ... /* error
  3277.                               /* note: you cannot unlock parts of a file with
  3278.                               /* 1 single unlock (where AP.recNo=0). Instead,
  3279.                               /* you must unlock each record individually--
  3280.                               /* that is, if you made any single-record locks
  3281. See: DriveRemoteXBsrc
  3282. ~DriveRemoteXBsrc
  3283. Func: DriveRemoteXB    Pack: RemotePack         Func:  86/Network
  3284. struct RemotePack RP;
  3285. RP.func = DRIVEREMOTEXB;      /* defined in BULLET.H
  3286. RP.handle = drive2check;      /* drive to check (0=default, 1=A:,2=B:,3=C:...)
  3287. rstat = BULLET(&RP);
  3288. if (rstat==0) {
  3289.   /* RP.isRemote set to 0 if drive local, 1 if remote
  3290.   /* RP.flags set to DX register as returned by DOS
  3291.   /* RP.isShare set to 0 if SHARE.EXE is not loaded, non-zero SHARE installed
  3292.   /* error  (like invalid drive)
  3293. See: FileRemoteXBsrc
  3294. ~FileRemoteXBsrc
  3295. Func: FileRemoteXB     Pack: RemotePack         Func:  87/Network
  3296. struct RemotePack RP;
  3297. RP.func = FILEREMOTEXB;       /* defined in BULLET.H
  3298. RP.handle = fileHandle;       /* file handle to check
  3299. rstat = BULLET(&RP);
  3300. if (rstat==0) {
  3301.    /* RP.isRemote set to 0 if file local, 1 if remote
  3302.    /* RP.flags set to DX register as returned by DOS
  3303.    /* RP.isShare set to 0 if SHARE.EXE is not loaded, non-zero SHARE installed
  3304.    /* error  (like invalid handle)
  3305. See: SetRetriesXBsrc
  3306. ~SetRetriesXBsrc
  3307. Func: SetRetriesXB     Pack: SetRetriesPack     Func:  88/Network
  3308. struct SetRetriesPack SRP;
  3309. SRP.func = SETRETRIESXB;
  3310. SRP.mode = 1;            /* 1=set to user values, 0=set DOS default
  3311. SRP.pause = 5000;        /* do 5,000 loops between retries
  3312. SRP.retries = 5;         /* try 5 times before giving up with error
  3313. rstat = BULLET(&SRP);
  3314. if (rstat !=0) ... /* error  (this routine is probably a waste of time)
  3315. See: DeleteFileDOSsrc
  3316. ~DeleteFileDOSsrc
  3317. Func: DeleteFileDOS    Pack: DOSFilePack        Func: 100/DOS
  3318. struct DosFilePack DFP;
  3319. DFP.func = DELETEFILEDOS;       /* defined in BULLET.H
  3320. DFP.filenamePtr = filename;
  3321. rstat = BULLET(&DFP);
  3322. if (rstat !=0) ... /* error
  3323. See: RenameFileDOSsrc
  3324. ~RenameFileDOSsrc
  3325. Func: RenameFileDOS    Pack: DOSFilePack        Func: 101/DOS
  3326. struct DosFilePack DFP;
  3327. DFP.func = RENAMEFILEDOS;       /* defined in BULLET.H
  3328. DFP.filenamePtr = orgFilename;
  3329. DFP.newNamePtr = newFilename;
  3330. rstat = BULLET(&DFP);
  3331. if (rstat !=0) ... /* error
  3332. See: CreateFileDOSsrc
  3333. ~CreateFileDOSsrc
  3334. Func: CreateFileDOS    Pack: DosFilePack        Func: 102/DOS
  3335. struct DosFilePack DFP;
  3336. DFP.func = CREATEFILEDOS;       /* defined in BULLET.H
  3337. DFP.filenamePtr = filename;
  3338. DFP.attr = 0;                   /* normal file directory attribute
  3339. rstat = BULLET(&DFP);
  3340. if (rstat !=0) ... /* error
  3341. See: AccessFileDOSsrc
  3342. ~AccessFileDOSsrc
  3343. Func: AccessFileDOS    Pack: DosFilePack        Func: 103/DOS
  3344. struct DosFilePack DFP;
  3345. DFP.func = ACCESSFILEDOS;       /* defined in BULLET.H
  3346. DFP.filenamePtr = filename;
  3347. DFP.asMode = 0x42;              /* attempt R/W DENY NONE access
  3348. rstat = BULLET(&DFP);
  3349. if (rstat !=0) ... /* error
  3350. See: OpenFileDOSsrc
  3351. ~OpenFileDOSsrc
  3352. Func: OpenFileDOS      Pack: DosFilePack        Func: 104/DOS
  3353. struct DosFilePack DFP;
  3354. DFP.func = OPENFILEDOS;         /* defined in BULLET.H
  3355. DFP.filenamePtr = filename;
  3356. DFP.asMode = 0x42;              /* open in R/W DENY NONE access
  3357. rstat = BULLET(&DFP);
  3358. if (rstat !=0) ... /* error else DFP.handle set to handle of open file
  3359. See: SeekFileDOSsrc
  3360. ~SeekFileDOSsrc
  3361. Func: SeekFileDOS      Pack: DosFilePack        Func: 105/DOS
  3362. struct DosFilePack DFP;
  3363. DFP.func = SEEKFILEDOS;         /* defined in BULLET.H
  3364. DFP.handle = handle;
  3365. DFP.seekoffset = 0L;            /* position 0 relative EOF (get length of file)
  3366. DFP.method = 2;                 /* seek from END of file
  3367. rstat = BULLET(&DFP);
  3368. if (rstat==0) {
  3369.    /* DFP.SeekOffset set to absolute current offset
  3370.    /* --in this case, the DFP.seekoffset equals then length of the file
  3371.    /* error
  3372. See: ReadFileDOSsrc
  3373. ~ReadFileDOSsrc
  3374. Func: ReadFileDOS      Pack: DosFilePack        Func: 106/DOS
  3375. struct DosFilePack DFP;
  3376. DFP.func = READFILEDOS;         /* defined in BULLET.H
  3377. DFP.handle = handle;
  3378. DFP.bytes = bytes2read;         /* 16-bit value, in this case 512 since that's
  3379. DFP.bufferPtr = dosBuff;        /* the size of dosbuff
  3380. rstat = BULLET(&DFP);
  3381. if (rstat==0) {
  3382.    if (DFP.bytes != bytes2read) { /* check if EOF processed
  3383.       /* hit EOF before reading all 512 bytes
  3384.    else
  3385.       /* ReadBuff filled with 512 bytes of data read from the current disk pos
  3386.       /* disk position moved to the last byte read + 1
  3387.    /* error
  3388. See: ExpandFileDOSsrc
  3389. ~ExpandFileDOSsrc
  3390. Func: ExpandFileDOS    Pack: DosFilePack        Func: 107/DOS
  3391. struct DosFilePack DFP;
  3392. DFP.func = EXPANDFILEDOS;       /* defined in BULLET.H
  3393. DFP.handle = handle;
  3394. DFP.seekOffset = bytes2expandby;
  3395. rstat = BULLET(&DFP);
  3396. if (rstat==0) {
  3397.    /* file expanded by number of bytes specified
  3398.    /* error
  3399. See: WriteFileDOSsrc
  3400. ~WriteFileDOSsrc
  3401. Func: WriteFileDOS     Pack: DosFilePack        Func: 108/DOS
  3402. struct DosFilePack DFP;
  3403. DFP.func = WRITEFILEDOS;        /* defined in BULLET.H
  3404. DFP.handle = handle;
  3405. DFP.bytes = bytes2write;        /* 16-bit value, in this case 512 since that's
  3406. DFP.buffPtr = dosBuff;          /* the size of dosbuff
  3407. rstat = BULLET(&DFP);
  3408. if (rstat=0xFFFE)               /* -2 that is
  3409.    /* disk full
  3410.    if (rstat !=0) ... /* error
  3411. Unlike ReadFileDOS, if the number of bytes actually written does not equal
  3412. bytes2write, the WriteFileDOS routine returns a DISK FULL error code (-2).
  3413. See: CloseFileDOSsrc
  3414. ~CloseFileDOSsrc
  3415. Func: CloseFileDOS     Pack: DosFilePack        Func: 109/DOS
  3416. struct DosFilePack DFP;
  3417. DFP.func = CLOSEFILEDOS;        /* defined in BULLET.H
  3418. DFP.handle =handle2close;
  3419. rstat = BULLET(&DFP);
  3420. if (rstat !=0) ... /* error
  3421. See: MakeDirDOSsrc
  3422. ~MakeDirDOSsrc
  3423. Func: MakeDirDOS       Pack: DosFilePack        Func: 110/DOS
  3424. struct DosFilePack DFP;
  3425. DFP.func = MAKEDIRDOS;          /* defined in BULLET.H
  3426. DFP.filenamePtr = newDirectoryName;
  3427. rstat = BULLET(&DFP);
  3428. if (rstat !=0) ... /* error
  3429. See: DeleteFileDOSsrc
  3430.